我将如何仅提取匹配文本的子字符串。
我有一个包含多行的 XML 文件。然而,这是我所关心的。
<url>/localhost/index.html</url>
我试过了
cat file.txt | grep -o '<url>.*</url>'
它给了我整条线。我只想/localhost/index.html
被打印。有没有我可以使用的其他选项,就像我在 Python 中知道的那样,您可以将正则表达式分组到子组中,然后选择要打印的那个。
如果您grep
不支持-P
(请参阅ruakh 的回答),您可以使用sed
:
sed -n 's|.*<url>\(.*\)</url>.*|\1|p'
如果您的版本grep
支持该-P
标志(对于 Perl 兼容的正则表达式),您可以使用lookaround:
grep -Po '(?<=<url>).*(?=</url>)' file.txt
我会使用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