我如何得到这个输出:
Found value: This order was placed for QT3000! OK?
或者
Found value: This order was placed for QT300
或者
Found value: 0
使用line.txt
andpattern.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
只能打印匹配的行(或单词),但不能真正修改匹配的数据。
Found value:
在包含数字的任何行前面插入,并打印这些行:$ sed -n '/[[:digit:]]/s/^/Found value: /p' line.txt Found value: This order was placed for QT3000! OK?
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
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
并不真正做那。