1

我将如何仅提取匹配文本的子字符串。

我有一个包含多行的 XML 文件。然而,这是我所关心的。

<url>/localhost/index.html</url>

我试过了

cat file.txt | grep -o '<url>.*</url>' 

它给了我整条线。我只想/localhost/index.html被打印。有没有我可以使用的其他选项,就像我在 Python 中知道的那样,您可以将正则表达式分组到子组中,然后选择要打印的那个。

4

3 回答 3

6

如果您grep不支持-P(请参阅ruakh 的回答),您可以使用sed

sed -n 's|.*<url>\(.*\)</url>.*|\1|p'
于 2013-05-24T23:41:42.957 回答
2

如果您的版本grep支持该-P标志(对于 Perl 兼容的正则表达式),您可以使用lookaround

grep -Po '(?<=<url>).*(?=</url>)' file.txt
于 2013-05-24T23:38:40.603 回答
2

我会使用sed

sed -n 's%.*<url>\(.*\)</url>.*%\1%p'

-n选项关闭默认打印。替换命令匹配单行上的<url>and标记,捕获其间的内容并包括匹配中的前导和尾随材料。</url>替换是捕获的材料,并且p手段打印。我使用%ins%%%而不是s///因为/出现在正则表达式中。另一种方法是使用斜杠并用反斜杠转义正则表达式中的斜杠。

Perl 也是可行和简单的:

perl -n -e 'print if s%.*<url>(.*)</url>.*%\1%'

创建一个 REPL ,-n但默认情况下不打印;只有在print替换操作进行替换时才会触发。

这个稍微复杂的 Perl 脚本<url>...</url>可以正确处理一行中的多个条目:

perl -n -e 'print "$1\n" while (s%.*?<url>(.*?)</url>%%)'

它使用非贪婪的正则表达式 ( .*?) 来避免吃太多信息。当替换操作检测并删除<url>...</url>带有可选前面的垃圾时,代码会在 URL 标记之间打印匹配的部分,后跟换行符。

给定数据:

xyz <url>/localhost/index1.html</url> pqr
xyz <url>/localhost/index2.html</url> abc <url>/localhost/index3.html</url> pqr
<url>/localhost/index4.html</url>
<url>/localhost/index5.html</url><url>/localhost/index6.html</url>
xyz <url>/localhost/index7.html</url> abc <url>/localhost/index3.html</url> xyz <url>/localhost/index9.html</url> abc <url>/localhost/index0.html</url> pqr

最后一个 Perl 脚本产生:

/localhost/index1.html
/localhost/index2.html
/localhost/index3.html
/localhost/index4.html
/localhost/index5.html
/localhost/index6.html
/localhost/index7.html
/localhost/index3.html
/localhost/index9.html
/localhost/index0.html
于 2013-05-24T23:46:52.470 回答