如何使用grep获取分组结果?

如何使用grep获取分组结果?

我如何得到这个输出:

Found value: This order was placed for QT3000! OK?

或者

Found value: This order was placed for QT300

或者

Found value: 0

使用line.txtandpattern.txt如下:

[nsaunders@rolly regex]$ 
[nsaunders@rolly regex]$ grep -e -f pattern.txt line.txt 
[nsaunders@rolly regex]$ 
[nsaunders@rolly regex]$ cat pattern.txt 
(.*)(\\d+)(.*)
[nsaunders@rolly regex]$ 
[nsaunders@rolly regex]$ cat line.txt 
This order was placed for QT3000! OK?
[nsaunders@rolly regex]$ 

利用某物相似的m.group(0)从一个教程在正则表达式上。

或许grep没有这样的概念作为:

Groups and capturing
Group number

Capturing groups are numbered by counting their opening parentheses from left to right. In the expression ((A)(B(C))), for example, there are four such groups:

    1       ((A)(B(C)))
    2       (A)
    3       (B(C))
    4       (C)

Group zero always stands for the entire expression.

Capturing groups are so named because, during a match, each subsequence of the input sequence that matches such a group is saved. The captured subsequence may be used later in the expression, via a back reference, and may also be retrieved from the matcher once the match operation is complete. 

答案1

假设中的模式pattern.txt

(.*)(\d+)(.*)

那么,将它与 GNU 一起使用grep将是一个问题

grep -E -f pattern.txt line.txt

即,搜索line.txt与 中列出的任何扩展正则表达式匹配的行pattern.txt,给定问题中的数据,生成

This order was placed for QT3000! OK?

您的命令的问题是您使用了-e -f.该-e选项用于明确表示“下一个参数是表达式”。这意味着-e -f将被解释为“要使用的正则表达式是-f”。然后,您将其应用于在命令行提到的两个文件中搜索匹配项。

第二个问题是\\d文件中的pattern.txt,它匹配反斜杠后跟字符d,即文字字符串\d

该模式还有一些其他“问题”。它首先使用非标准表达式来匹配数字,\d。最好将其写为[[:digit:]]或 范围[0-9](在 POSIX 标准语言环境中)。由于正则表达式匹配子字符串,与始终自动锚定的文件名通配模式相反,因此.*不需要模式的任何位。同样,根本不需要括号,因为它们在模式中没有任何作用。也不+需要,因为单个数字将与前面的表达式匹配(单个数字是“一个或多个数字”)。

这意味着要提取包含(至少)一位数字的所有行,您可以使用模式[[:digit:]][0-9],或者\d如果您想继续在 GNU 中使用类似 Perl 的表达式grep,而不进行其他修饰。关于它们之间的区别,请参见[0-9]、[[:digit:]] 和 \d 之间的区别

要获得问题中显示的三个不同输出,请使用sed而不是grep。你之所以要使用,sed是因为grep只能打印匹配的行(或单词),但不能真正修改匹配的数据。

  1. Found value: 在包含数字的任何行前面插入,并打印这些行:

    $ sed -n '/[[:digit:]]/s/^/Found value: /p' line.txt
    Found value: This order was placed for QT3000! OK?
    
  2. Found value:在包含数字的任何行前面插入,并打印这些行直到找到的第 3 个数字的末尾(或打印到最多第三位数字;如果该行的第一个数字子串中的连续数字较少,则可能会在末尾输出较少的数字):

    $ sed -n '/[[:digit:]]/s/\([^[:digit:]]*[[:digit:]]\{1,3\}\).*/Found value: \1/p' line.txt
    Found value: This order was placed for QT300
    
  3. Found value:在包含数字的任何行前面插入,并打印该行的最后一个数字:

    $ sed -n '/[[:digit:]]/s/.*\([[:digit:]]\).*/Found value: \1/p' line.txt
    Found value: 0
    

使用与您使用的等效的正则表达式,我们可以看到它匹配文本的哪些位:

$ sed 's/\(.*\)\([[:digit:]]\{1,\}\)\(.*\)/(\1)(\2)(\3)/' line.txt
(This order was placed for QT300)(0)(! OK?)

请注意,\2仅匹配该行的最后一个数字,因为前面的数字.*是贪婪的。

答案2

我认为您无法在 grep 中访问捕获组,但在 Perl 中可以。

$ echo 'foo123bar' | re='(.*)(\d+)(.*)' \
     perl -lne 'if (m/$ENV{re}/) { printf "Found value: %s\n", $_ for @{^CAPTURE} }'
Found value: foo12
Found value: 3
Found value: bar

它基本上只是说将输入行(由 隐式读取-n)与 env 变量中的内容re(在命令行上设置以传递模式)进行匹配,并@{^CAPTURE}使用前缀打印所有捕获的文本(来自数组 )(如果有)一场比赛。

答案3

来自爪哇:

jshell> /reset
|  Resetting state.

jshell> /open grep.jsh
This order was placed for QT3000! OK?
This order was placed for QT300
0

jshell> /list

   1 : import static java.lang.System.out;
   2 : String text = "This order was placed for QT3000! OK?";
   3 : String patternString1 = "(.*)(\\d+)(.*)";
   4 : Pattern pattern = Pattern.compile(patternString1);
   5 : Matcher matcher = pattern.matcher(text);
   6 : matcher.find()
   7 : out.println(matcher.group(0))
   8 : out.println(matcher.group(1))
   9 : out.println(matcher.group(2))

jshell> 

我对使用更感兴趣,group但没有意识到这grep并不真正那。

相关内容