对于三个连续RE的每个完全任意的一组," re1 ( re2 ) re3 &#34 ;,我想要一个工具(或一个单行),输出与 re2 相匹配的所有内容。 (\1
)
我正在寻找一个常用的命令行工具,它将使用任意正则表达式提取信息,例如grep -o
,但是可以像上下文一样使用expr match
。我在grep -o
中想要的功能是对文件进行迭代,只打印匹配,除了我不想打印出上下文;我在expr match
中想要的功能是从上下文中提取的功能(即提取子表达式)。基本上我想匹配每个子表达并打印它,只有它出来。
注意:以下只是一个简单的例子。我的问题是一般的问题,可能涉及从引用的材料到提取XML标签,任何你可以编写正则表达式的东西。 ERE很好,PCRE更好。
例如,假设我想在括号内的一行内打印出所有内容,但不想打印括号。如果我grep -Eo '([^()]*?)'
我得到了所有的比赛,但他们周围有括号:
输入:
$ grep -Eo '\([^()]*?\)'
foo (bar) baz (bat)
输出:
(bar)
(bat)
正确:两个孤立的项目。 不正确:他们有parens。
或者我可以使用expr match
:
$ expr match 'foo (bar) baz (bat)' '.*(\([^()]*\)).*'
这给了我:
bat
正确地剥离了parens,但错过了第一次出现。
我想过如何在sed
中做到这一点;一个人可以使用替换,但是sed
会在第一次出现时吃掉expr 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问题,很多解决方案都会回答特定问题的具体特征,但我想要一个通用的解决方案。
答案 0 :(得分:1)
如果你有gnu grep,那么你可以使用lookaheads一步完成:
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:
答案 1 :(得分:-2)
受到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
附带的宏,有这种不寻常的技术(称为&#34;聚焦&#34;)内部重新排列电子邮件地址并暂时添加无关的语法它们更容易处理。