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