我在这里有一个正则表达式,它根据站点工作:
https://regex101.com/r/doj4We/1
正则表达式:<<act ("([^"\]|\.)*")
text:
<<act "want" "don't want">><</act>>
<<act ""want"" "don't want">><</act>>
组1应该捕获";想要";以及"\"想要"&";,根据该网站的说法,确实如此。
但是,如果我把这个文本保存在一个文件中,然后执行这个命令:
cat tmp | sed -Ern 's/<<act ("([^"\]|\.)*")/1/p'
这是输出:
"want" "don't want">><</act>>
""want"" "don't want">><</act>>
为什么sed的行为与这个网站所说的不一样?当我尝试像这样使用awk的发电站时,我注意到了同样的问题:
cat tmp | awk '{ r = gensub(/<<act ("([^"\]|\.)*")/, "\1", "g"); print r;}'
就其价值而言,我正在使用cygwin。
您将sed
与s
substitution命令一起使用,因此将搜索并替换找到的匹配项。您想要获得组1的值,因此您需要匹配捕获组之前的零件和之后的,以删除它们以保持您想要的。
你可以使用
sed -En 's/<<act ("([^"]|\.)*").*/1/p'
# ^^
.*
将匹配任何文本,并将被删除。这也意味着在字符串的开头只能有<<act
。还要注意,由于括号表达式不支持正则表达式转义,[^"]
就足够了,不需要对进行双转义。
注意选项:-E
启用POSIX ERE regex语法,n
抑制默认行输出,p
打印替换结果。
您的正则表达式<<act ("([^"\]|\.)*")
与awk
将按原样运行。更重要的是,如果你使用gnu-awk
,那么你真的不需要做任何替换。它可以在单个match
函数中完成,如下所示:
awk 'match($0, /<<act ("([^"\]|\.)*")/, m) { print m[1] }' file
"want"
""want""
对于POSIX awk,您可以使用此awk
:
/awk '$1 == "<<act" && $2 ~ /"([^"\]|\.)*"/{ print $2 }' file