繁体   English   中英

使用正则表达式提取字符串的命令行工具

[英]Command-line tool to extract strings using regex

对于三个受污染的RE的每一个完全任意的集合,即“ re1re2re3 ”,我想要一个工具(或单线 )输出与re2匹配的所有内容。 \\1

我正在寻找一种通用的命令行工具,该工具将使用任意正则表达式(如grep -o提取信息,但要具有上下文意识,如expr match 我希望在grep -o使用的功能是在文件上进行迭代,并且仅打印匹配项, 我不想打印出上下文。 我想要在expr match中使用的功能是能够从上下文中提取内容(即,提取子表达式)。 基本上,我想匹配每个子表达式并仅将其打印出来。

注意:以下仅是一个简单示例。 我的问题是一个笼统的问题,涉及从引用材料到提取XML标签的所有问题,您可以为其编写正则表达式的任何问题。 ERE很好,PCRE更好。

例如,假设我要打印出括号内的一行中的所有内容,但不想打印括号。 如果我执行grep -Eo '([^()]*?)'我会得到所有匹配项,但是它们周围都有括号:

输入:

$ grep -Eo '\([^()]*?\)' 
foo (bar) baz (bat)

输出:

(bar)
(bat)

正确:两个孤立的项目。 错误的:他们有括号。

或者我可以使用expr match

$ expr match 'foo (bar) baz (bat)' '.*(\([^()]*\)).*'

这给了我:

bat

正确地删除了括号,但是错过了第一次出现。

我想过在sed该怎么做; 一个人可以使用替换,但是sedexpr match这样吃掉第一个出现的东西:

$ echo 'foo (bar) baz (bat)' | sed 's/.*(\([^()]*\)).*/\1/g'
bat

此外,我不认为sed旨在从一行输入生成两行或更多行输出(就像grep -o一样); 它更像是逐行工具。 如果sed可以选择将\\ n子表达式匹配项放入模式空间或保持有效的空间。

我认为这可能在gawk可行,但似乎并不简单。 sed一样, gawk可以进行替换; grep一样,它可以匹配子字符串; expr match ,它在一行中有多个引用存在麻烦(尽管与expr match不同,它有很多解决方法)。

它可能可以在Perl中完成,但是会涉及某种复杂的循环。

通过查看许多相关的SO问题,许多解决方案针对特定问题的特定特征做出了答复,但是我想要一个通用的解决方案。

如果您有gnu grep,则可以使用先行提示一步完成此操作:

s='foo (bar) baz (bat)'

grep -Po '(?<=\()[^()]*(?=\))' <<< "$s"
bar
bat

或使用gnu awk:

awk -v FPAT='\\([^()]*\\)' '{for (i=1; i<=NF; i++) {gsub(/[()]/, "", $i); print $i}}' <<< "$s"
bar
bat

或使用sed:

sed -E 's/[^()]*\(([^()]*)\)/\1:/g' <<< "$s"
bar:bat:

sendmail *的启发,我认为也许只有两步的过程可能会起作用,而只有一步却没有。 解决方案很简单; 使用grep -o打印出匹配项,并使用sed删除不需要的上下文:

$ re='\(([^()]*)\)'; echo 'foo (bar) baz (bat)' | grep -Eo "$re" | sed -r "s/$re/\1/1"
bar
bat

$ re="<([^<>]*)>"; echo "I <strong>really</strong> want <A href="http://foo.com">this</A>" | grep -Eo "$re" | sed -r "s/$re/\1/1"
strong
/strong
A href=http://foo.com
/A

$ re="<[^<>]*>([^<]*)<[^<>]*>"; echo "I <strong>really</strong> want <A href="http://foo.com">this</A>" | grep -Eo "$re" | sed -r "s/$re/\1/1"  
really
this

$ re="'([^']*)'"; echo "His name was 'John', her name was 'Jane'" | grep -Eo "$re" | sed -r "s/$re/\1/1"
John
Jane

您只需要在正则表达式中转义任何斜线或执行某些操作来解决sed分隔符问题。

* sendmail ,或者不如说是来与宏sendmail ,有这种非同寻常的技术(所谓的“重点”)的内部清理的电子邮件地址,并临时增加多余的语法,使他们更容易处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM