我如何使用后缀来匹配单引号或双引号?

How can I use a look after to match either a single or a double quote?

我有一系列要提取的字符串:

hello.this_is("bla bla bla")
some random text
hello.this_is('hello hello')
other stuff

我需要得到的(从很多文件中,但这在这里并不重要)是hello.this_is()之间的内容,所以我想要的输出是:

bla bla bla
hello hello

如您所见,括号内的文本可以用双引号或单引号引起来。

如果这只是单引号,我会像这样使用后视和前视:

grep -Po "(?<=hello.this_is\(').*(?=')" file
#                            ^      ^
# returns ---> hello hello

同样,要从双引号中获取字符串,我会说:

grep -Po '(?<=hello.this_is\(").*(?=")' file
#                            ^      ^
# returns ---> bla bla bla

但是,我想匹配这两种情况,所以它同时获得单引号和双引号。我尝试使用 $'' 进行转义,但无法成功:

grep -Po '(?<=hello.this_is\($'["\']').*(?=$'["\']')' file
#                            ^^^^^^^^      ^^^^^^^^

我当然可以用ASCII码说:

grep -Po '(?<=hello.this_is\([72]).*' file

但我想使用引号和单引号,因为 047042 对我来说不像单引号和双引号那么具有代表性。

使用捕获组并查找其内容,如下所示:

grep -Po 'hello\.this_is\(([7"])((?!).|\.)*\)' file

这也关心转义字符,例如hello.this_is("bla b\"la bla")

live demo here

如果输出应该是括号之间的内容,则同时使用 \K 和正前瞻:

grep -Po 'hello\.this_is\(([7"])\K((?!).|\.)*(?=\))' file

输出:

bla bla bla
hello hello

注意:此答案底部的 sed 命令仅在您的字符串表现得像

时才有效
"foo"

'bar'

一旦您的字符串开始出现异常 :) 如:

"hello \"world\""

它将不再有效。

您的输入看起来像源代码。对于稳定的解决方案,我建议使用该语言的解析器来提取字符串。


对于琐碎的用例:

您可以使用 sed。该解决方案应该适用于任何 POSIX 平台,而 grep -oP 仅适用于 GNU grep:

sed -n 's/hello\.this_is(\(["'\'']\)\([^"]*\)\(["'\'']\).*//gp' file
#                                    ^^^^^^^^              ^^
#                                          capture group 2 ^

基于 revo 和 hek2mgl 的优秀答案,我最终使用了 grep 这样的:

grep -Po '(?<=hello\.this_is\((["'\''])).*(?=)' file

可以解释为:

  • grep
  • -Po 使用 Perl 正则表达式机器并只打印匹配项
  • '(?<=hello\.this_is\((["'\''])).*(?=)' 表达式
    • (?<=hello\.this_is\((["'\''])) 后视:搜索字符串前面有 "hello.this_is(",后面跟着 '"。另外,捕获最后一个字符以供稍后使用。
    • .* 匹配一切...
    • (?=)直到捕获的字符(即'")再次出现。

这里的关键是使用["'\'']来表示'"。通过执行 '\'',我们将关闭封闭表达式,填充文字 '(我们必须转义)并再次打开封闭表达式。