Text-Processing

如何使用 grep 獲取組結果?

  • June 15, 2020

我將如何獲得此輸出:

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

或者

Found value: This order was placed for QT300

或者

Found value: 0

使用line.txtpattern.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. 

假設中的模式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:]]or [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?
  1. Found value: 在包含數字的任何行前面插入,並將這些行列印到找到的第 3 個數字的末尾(或最多到第 3 個數字;如果第一個子字元串中的連續數字較少,則可能在末尾輸出較少的數字線上的數字):
$ sed -n '/[[:digit:]]/s/\([^[:digit:]]*[[:digit:]]\{1,3\}\).*/Found value: \1/p' line.txt
Found value: This order was placed for QT300
  1. 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僅匹配行上的最後一位數字,因為前面.*是貪婪的。

引用自:https://unix.stackexchange.com/questions/592792