我对Bash真的很陌生,所以对大多数人来说这听起来很傻。 我正在尝试从文本文件中获取一些文件名列表。试图用sed和awk做这件事,但是用我有限的知识无法使它工作。
这是一个示例文件内容:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 13.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="471.677px" height="126.604px" viewBox="0 0 471.677 126.604" enable-background="new 0 0 471.677 126.604"
xml:space="preserve">
<rect x="0.01" y="1.27" fill="none" width="471.667" height="125.333"/>
<text transform="matrix(1 0 0 1 0.0098 8.3701)"><tspan x="0" y="0" font-family="'MyriadPro-Regular'" font-size="10">/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf</tspan><tspan x="0" y="12" font-family="'MyriadPro-Regular'" font-size="10">/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf</tspan><tspan x="0" y="24" font-family="'MyriadPro-Regular'" font-size="10">/Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf</tspan></text>
</svg>
我希望从此示例中获得一个具有以下确切内容的新文本文件:
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf
我想告诉sed打印“font-size"10">
”和“</tspan>
”之间的所有匹配条目,但是...我得到的最好的是一个文件,整行包含我的字段分隔符。< / p>
如果你能解释完成的每一步,那就太棒了。
答案 0 :(得分:1)
这个怎么样:
cat file.xml | sed -e's/^[^>]*>//' -e's/<.*$//' | grep \\.
这不是一般目的,但要完全通用会更复杂(XML需要完整的解析器等)。
基本上,sed脚本有两个部分。首先,从行首(^)开始删除所有字符到第一个“&gt;”字符。请注意,我匹配所有非“&gt;”为了做到这一点。第二部分剥离了最左边的所有字符“&lt;”字符到行尾。由于第二部分是在第一部分之后出现的,所以它是在第一部分完成后完成的,这就是为什么它不会擦掉整条线。
然后,grep语句只返回带有“。”的行。在它们中,只有文件名剩余的行。
希望有所帮助!
答案 1 :(得分:0)
sed
命令将为
sed -n 's|font-size="[0-9]*".\(.*\)</tspan.*|\1|p' file.xml
------------------- -- ---------
prefix part \1 suffix
这是它的工作原理,
-n
禁止从缓冲区打印所有行p
表示要打印替换的缓冲区'|'
代替通常'/'
,有助于轻松过滤路径分隔符font-size="[0-9]*".
和`之间的所有内容
\(
和\)
之间的部分是我们感兴趣的部分
\1
表示我们希望将其保留在打印缓冲区中此命令使用group operator which is described here。
在你的文件中,这给了,
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf
请注意,获取正确的前缀和后缀字符串以获取所有匹配项非常重要。在您的示例中,这些是我在上面找到的font-size
和tspan
部分。但是,对于文件中的所有文件字符串可能不是这种情况。所以检查一下。
答案 2 :(得分:0)
Sed和awk通常不是阅读XML的正确方法。它们可能有用,但XML可以随时更改布局并破坏内容,同时仍然是完全有效的XML。
更好的是使用像Perl这样的东西。通过CPAN安装XML :: Smart模块,或者使用“sudo apt-get install libxml-smart-perl”安装在ubunto上。
然后是这样一个简单的脚本:
use strict;
use diagnostics;
use XML::Smart;
my $xml = XML::Smart->new ("svg.xml") || die "Cannot read XML: $!.";
my $version = $xml->{svg}{version} || die "Cannot determine SVG version.";
foreach my $file ($xml->{svg}{text}{tspan}('@')) {
print $file->content . "\n";
}
将其另存为svg.pl.将XML保存为svg.xml。
$ perl svg.pl / Volumes / Secondary500 / Temp / Untitled-2_Layer 1 copy 2.pdf / Volumes / Secondary500 / Temp / Untitled-2_Layer 1 copy.pdf / Volumes / Secondary500 / Temp / Untitled-2_Layer 1.pdf
此:
玩得开心!
答案 3 :(得分:0)
如果您想要解析XML,那么其他人已经给出了为什么要使用正确的XML解析器的良好答案,但就如何在sed中解决如何实现这一点,如果您遇到类似的问题:< / p>
#Full Command
sed -n 's/^[^<]*<tspan[^>]*>\([^<]*\)<.*/\1/p' ~/your_file.xml
除非被要求,否则n选项会使sed不发送任何输出。通常sed将在末尾重复模式空间,这可能会令人困惑
从s开始,因为是[s] ubstitute。接下来的“/”告诉sed我们将使用“/”来划分脚本的不同部分。
从行的开头(^)抓取所有内容以及之后的所有内容都不是一个开括号([^`&lt;] *)。这将在稍后被丢弃。
抓住tspan及其之后的所有不是结束括号的内容([^&gt;] *&gt;)。这也将被丢弃。
抓住所有关闭括号之后的所有内容,这不是一个开放的括号。这是我们要保留的部分,因此我们将其括在转义括号中。 “([^&LT;] *)”
从最后一个右括号中取出所有内容,直到“&lt;。*”行结束。我们也会抛弃它。
命令的第二部分:\ 1 所有这些意味着:重复我们之前使用的第一组转义括号中的内容。只有一组括号,所以\ 2,\ 3等在这里没有意义,但你可以在其他脚本中使用它们。在你的情况下,你想重复我们内部匹配的内容
最后:“p”使sed打印出匹配。这适用于开头的-n,相当于“不打印任何东西”,除了'匹配'
希望这有用......
答案 4 :(得分:0)
如果你有xmlgawk,你可以轻松搞定。
@load xml
BEGIN {
XMLMODE = 1;
XMLCHARSET = "utf-8";
}
XMLCHARDATA {
data = $0;
}
XMLENDELEM == "tspan" {
print data;
}
和
$ xgawk -f pick_from_svg.awk sample.xml
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf
答案 5 :(得分:0)
awk 'BEGIN{RS="font-size=\"10\">|</tspan>"}/pdf/' xml.txt
$ awk 'BEGIN{RS="font-size=\"10\">|"}/pdf/' xml.txt /Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf /Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf /Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf
这段代码可能是最简单的,没有凌乱的正则表达式,它非常易于扩展,您可以根据自己的喜好进行调整。我决定匹配术语'pdf',因此匹配代码的/pdf/
部分,但是,例如,如果你想要匹配的其他文件不是pdf,而是包含'Volumes'这个词你可以简单地使用/Volumes/
。