web-dev-qa-db-ja.com

パイプ文字を含むパターンを持つ複数のパターンをgrepするにはどうすればよいですか?

2つのパターンのいずれかに一致する複数のファイル内のすべての行を検索したい。入力して探しているパターンを見つけようとしました

grep (foo|bar) *.txt

しかし、シェルは|をパイプとして解釈し、barが実行可能ファイルでない場合は文句を言います。

同じファイルセット内の複数のパターンをgrepするにはどうすればよいですか?

681
Dan
egrep "foo|bar" *.txt

または

grep "foo\|bar" *.txt
grep -E "foo|bar" *.txt

gnu-grepのmanページを選択的に引用します:

   -E, --extended-regexp
          Interpret PATTERN as an extended regular expression (ERE, see below).  (-E is specified by POSIX.)

Matching Control
   -e PATTERN, --regexp=PATTERN
          Use PATTERN as the pattern.  This can be used to specify multiple search patterns, or to protect  a  pattern
          beginning with a hyphen (-).  (-e is specified by POSIX.)

(...)

   grep understands two different versions of regular expression syntax: “basic” and “extended.”  In  GNU grep,  there
   is  no  difference  in  available  functionality  using  either  syntax.   In  other implementations, basic regular
   expressions are less powerful.  The following description applies to extended regular expressions; differences  for
   basic regular expressions are summarized afterwards.

最初は読みませんでしたので、微妙な違いを認識できませんでした。

Basic vs Extended Regular Expressions
   In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead  use  the
   backslashed versions \?, \+, \{, \|, \(, and \).

例から学んだので、私はいつもegrepと不必要に括弧を使いました。今、私は何か新しいことを学びました。 :)

109
user unknown

TC1が言ったように、-Fは使用可能なオプションのようです:

$> cat text
some text
foo
another text
bar
end of file

$> patterns="foo
bar" 

$> grep -F "${patterns}" text
foo
bar

まず、特殊文字には引用符を使用する必要があります。第二に、それでも、grepは代替を直接理解しません。 egrepを使用する必要があります、または(GNU grepのみ)grep -E

egrep 'foo|bar' *.txt

(代替がより大きな正規表現の一部でない限り、括弧は不要です。)

17
geekosaur

正規表現が必要ない場合は、次のように、複数の-eパラメータを指定してfgrepまたはgrep -Fを使用する方がはるかに高速です。

fgrep -efoo -ebar *.txt

fgrep(またはgrep -F)は、正規表現ではなく固定文字列を検索するため、通常のgrepよりもはるかに高速です。

8

以下のコマンドを試して結果を得ることができます:

egrep 'rose.*Lotus|lotus.*rose' some_file
6
Abhishek

パイプ(|)は特殊なシェル文字であるため、エスケープする(\|)か、マニュアルに従って引用する( man bash ):

引用は、シェルに対して特定の文字または単語の特別な意味を削除するために使用されます。これを使用して、特殊文字の特別な扱いを無効にし、予約語がそのように認識されないようにし、パラメータの展開を防ぐことができます。

二重引用符で文字を囲むと、引用符内のすべての文字のリテラル値が保持されます

引用符で囲まれていないバックスラッシュ(\)はエスケープ文字です。

参照: Bashでエスケープする必要がある文字は?

次にいくつかの例を示します(まだ言及されていないツールを使用)。

  • ripgrep を使用:

    • rg "foo|bar" *.txt
    • rg -e foo -e bar *.txt
  • git grep を使用:

    • git grep --no-index -e foo --or -e bar

      注:--and--or--notなどのブール式もサポートしています。

行ごとのAND演算については、次を参照してください。 複数のANDパターンを使用してgrepを実行する方法

ファイルごとのAND演算については、次を参照してください。 ファイルに存在する複数の文字列または正規表現をすべて確認する方法

4
kenorb

複数のパターンをgrepする安価で陽気な方法:

$ echo "foo" > ewq ; echo "bar" >> ewq ; grep -H -f ewq *.txt ; rm ewq
3
DHDHDHD

日付が愚かにフォーマットされたアクセスログがありました:[30/Jun/2013:08:00:45 +0200]

しかし、私はそれを次のように表示する必要がありました:30/Jun/2013 08:00:45

問題は、grepステートメントで「OR」を使用すると、2つの別々の行で2つの一致式を受け取っていたことです。

これが解決策です:

grep -in myURL_of_interest  *access.log  | \
grep -Eo '(\b[[:digit:]]{2}/[[:upper:]][[:lower:]]{2}/[[:digit:]]{4}|[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}\b)'   \
| paste - - -d" " > MyAccess.log
3
tsmets

TL; DR:複数のパターンの1つに一致した後でさらに多くのことを実行する場合は、\(pattern1\|pattern2\)のように囲みます。

例:「date」という名前を含む変数がStringまたはintとして定義されているすべての場所を検索します。 (例: "int cronDate ="または "String textFormattedDateStamp ="):

_cat myfile | grep '\(int\|String\) [a-zA-Z_]*date[a-zA-Z_]* =' 
_

_grep -E_を使用すると、括弧やパイプをエスケープする必要がありません。つまり、grep -E '(int|String) [a-zA-Z_]*date[a-zA-Z_]* ='

2
jeremysprofile

これは私のために働く

root@gateway:/home/sshuser# aws ec2 describe-instances --instance-ids i-2db0459d |grep 'STATE\|TAG'

**STATE**   80      stopped

**STATE**REASON     Client.UserInitiatedShutdown    Client.UserInitiatedShutdown: User initiated shutdown

**TAGS**    Name    Magento-Testing root@gateway:/home/sshuser#
1
Mansur Ali

これには複数の方法があります。

  1. grep 'foo\|bar' *.txt
  2. egrep 'foo|bar' *.txt
  3. find . -maxdepth 1 -type f -name "*.txt" | xargs grep 'foo\|bar'
  4. find . -maxdepth 1 -type f -name "*.txt" | xargs egrep 'foo|bar'

3番目と4番目のオプションは、ファイルでのみgrepを実行し、ディレクトリに.txt彼らの名前で。
そのため、ユースケースに従って、上記のオプションのいずれかを使用できます。
ありがとう!!

1

@ geekosaur's answer に追加するには、タブとスペースも含む複数のパターンがある場合、次のコマンドを使用します

grep -E "foo[[:blank:]]|bar[[:blank:]]"

どこ [[:blank:]]は、スペースまたはタブ文字を表すRE文字クラスです

1
Fuseteam