web-dev-qa-db-ja.com

特定のパターンに基づいて行をgrepする方法は?

次の2行を含むファイルがあるとします。

2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
2014-05-05      09:12:17    /aa/bbbb/cccccc?dddddddd    16767 

パターンを含む行を取得する必要があります/aa/bbbb/ccccccのみ、余分な文字を含む2行目、つまり?ddddddddは必要ありません。今私が試したとき

grep '/aa/bbbb/cccccc' file

次に、両方の行が選択されます。完全な行が必要なので、grep -oは解決策になりません。

grepを使用して可能な解決策は何ですか?検索パターンに基づいて最初の行のみが選択されますか?

8
heemayl

-PPerl-regexp)パラメーターを使用する以下のgrepコマンドを試してください。

grep -P '(?<!\S)/aa/bbbb/cccccc(?!\S)' file
  • (?<!\S)この否定的な後読みは、文字列/aa/bbbb/ccccccの前にある文字が非スペース文字ではなく任意のものであることを表明します。

  • (?!\S)負の先読みは、一致後の文字がスペース以外の文字ではなく任意のものであることを表明します。

別のgrep、

 grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file

Pythonを介して、

script.py

#!/usr/bin/python3
import re
import sys
file = sys.argv[1]
with open(file, 'r') as f:
    for line in f:
        for i in line.split():
            if i == "/aa/bbbb/cccccc":
                print(line, end='')

上記のコードをファイルに保存し、script.pyという名前を付けます。次に、上記のスクリプトを実行します

python3 script.py /path/to/the/file/you/want/to/work/with
7
Avinash Raj

最も簡単な方法は、パターンの後にスペースを追加することです。

$ grep '/aa/bbbb/cccccc ' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

または、あらゆる種類の空白に一致させるには:

$ grep  '/aa/bbbb/cccccc[[:space:]]' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

または

$ grep -P '/aa/bbbb/cccccc\s+' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

または、 正の先読み で:

$ grep -P '/aa/bbbb/cccccc(?=\s)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

または、 負の先読み

$ grep -P '/aa/bbbb/cccccc(?!\S)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

または、一致を逆にすることができます。

$ grep  -v 'c?' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

または、パターン(末尾の空白なし)のみを含む行にも一致させるには:

grep -P '/aa/bbbb/cccccc(\s+|$)' file 
grep -E '/aa/bbbb/cccccc(\s+|$)' file 

または、小さなスクリプトを使用することもできます。

  • Awkの場合:

    $ awk '$3=="/aa/bbbb/cccccc"' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    

    または、パターンがどのフィールドにあるのかわからない場合

    $ awk '{for(i=1;i<=NF;i++){if($i=="/aa/bbbb/cccccc"){print}}}' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
  • Perlで

    $ Perl -ane 'print if grep {$_ eq "/aa/bbbb/cccccc"} @F' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
10
terdon

@ AvinashRajanswer を補完するには、次のようなコマンドも使用できます。

grep -P '/a+/b+/c+(?!\S)' file
2
αғsнιη