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


8

次の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のみを含む行を取得する必要があり?ddddddddます。余分な文字を含む2行目は必要ありません。今私が試したとき

grep '/aa/bbbb/cccccc' file

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

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

回答:


7

-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

ありがとう。ところで、これはperl正規表現ではなく通常/拡張正規表現を使用して実行できますか?
heemayl 2014年

1
terdonが投稿したように、あなたは単純にgrep '/aa/bbbb/cccccc ' file
Avinash Raj 14

ただし、上記では/aa/bbbb/cccccc文字列のみの行は出力されません。
Avinash Raj 14年

あなたもそれと一致することができますgrep -E '/aa/bbbb/cccccc(\s+|$)' file
terdon

はい、このようにgrep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file
Avinash Raj 2014

10

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

$ 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
    

@terdonではgrep -v 'c?' filegrep -v '?' filefileには2行しかないため、使用しません。
αғsнιη

@KasiyA確かに、私はパターンの一部を保持したかっただけです。しかし、この特定のケースでgrep -v '?'は十分です。
terdon 2014年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.