ファイル内のこれまたはその(2つのこと)をgrepするにはどうすればよいですか?


38

「then」と「there」を含むファイルがあります。

できます

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

そして私はできる

$ grep "there " x.x
If there is no blob none some will be created

1つの操作で両方を検索するにはどうすればよいですか?私は試した

$ grep (then|there) x.x

-bash:予期しないトークン `( 'の近くの構文エラー

そして

grep "(then|there)" x.x
durrantm.../code
# (Nothing)

回答:


54

式を引用符で囲む必要があります。受信しているエラーは、bash (が特殊文字として解釈した結果です。

また、拡張正規表現を使用するようにgrepに指示する必要があります。

$ grep -E '(then|there)' x.x

拡張正規表現がなければ、あなたはエスケープする必要があり|()。ここでは単一引用符を使用していることに注意してください。Bashは、二重引用符内のバックスラッシュを特別に扱います。

$ grep '\(then\|there\)' x.x

この場合、グループ化は必要ありません。

$ grep 'then\|there' x.x

次のような場合に必要になります。

$ grep 'the\(n\|re\)' x.x

3
grep $'then\nthere'およびも参照してくださいgrep -e then -e there\|BREでは標準ではないことに注意してください。残りは。バッシュの扱いだけ前に特別に二重引用符内のバックスラッシュ"$\ `および改行。
ステファンシャゼル

1
の目的はx.x何ですか?
アレックス

7

ちょっとした補足として、ほとんどのフレーバーにはegrepと呼ばれるコマンドがあり、これは単に-Eを付けたgrepです。私は個人的にはるかに入力するのが好きです

egrep "i(Pod|Pad|Phone)" access.log

grep -Eを使用するより


2

(または少なくとも私の)manページのREGULAR EXPRESSIONSで文書化されているものは、実際には拡張正規表現用です。

grepは、「basic」、「extended」、「perl」の3つの異なるバージョンの正規表現構文を理解します。GNUgrepでは、基本構文と拡張構文の間に使用可能な機能に違いはありません。他の実装では、基本的な正規表現はそれほど強力ではありません。 次の説明は、拡張正規表現に適用されます。基本的な正規表現の違いは後で要約されます。

しかし、grepはデフォルトではそれらを使用しません- -Eスイッチが必要です:

grep "(then|there)" x.x

なぜなら(再びmanページから):

基本正規表現と拡張正規表現

基本的な正規表現では、メタ文字?、+、{、|、(、および)は特別な意味を失います。代わりに、バックスラッシュバージョンの\?、+、{、\ |、(、および)を使用します。

以下も使用できます。

grep "then\|there" x.x

この場合、括弧は不要です。


0

Bashのエレガントなシンプルさは、巨大なmanページで失われるようです。

上記の優れたソリューションに加えて、bashがステートメントをどのように解析および解釈するかについてのチートシートを提供したいと思いました。次に、このロードマップを使用して、質問者が提示した例を解析し、意図したとおりに動作しない理由をよりよく理解できるようにします。


注:シェルスクリプト行は直接使用されます。入力された入力行は最初に履歴展開されます。

各bash行は最初にトークン化されます。つまり、トークンと呼ばれるものに切り刻まれます。(トークン化は、中かっこ、チルダ、パラメータ、コマンド、算術、プロセス、単語分割、ファイル名展開など、他のすべての展開の前に行われます。)

ここでのトークンは、これらの特別なメタ文字のいずれかで区切られた(区切られた)入力行の一部を意味します。

space,  - White space...
tab, 
newline,

‘<’,    - Redirection & piping...
‘|’, 
‘>’
‘&’,    - And/Both < | > | >>  .or.  &<file descriptor>

‘;’,    - Command termination

‘(’,    - Subshell, closed by -     ‘)’

Bashは他の多くの特殊文字を使用しますが、これらの10個だけが初期トークンを生成します。

ただし、これらのメタ文字もトークン内で使用する必要がある場合があるため、それらの特別な意味を取り除く方法が必要です。これはエスケープと呼ばれます。エスケープは、1つ以上の文字のストリングを引用する(つまり'xx..'"xx..")か、個々の文字の前にバックスラッシュを付ける(つまり\x)ことによって行われます。(引用符も引用する必要があり、二重引用符がすべてを引用するわけではないため、これよりも少し複雑になりますが、この単純化は今のところ行います。)

bashの引用を、他の言語のようにテキストの文字列を引用するという考えと混同しないでください。bashの引用符の間にあるのは文字列ではなく、トークンを区切らないようにメタ文字がエスケープされている入力行のセクションです。

'、との間には重要な違いがありますが、それは"また別の日です。

残りのエスケープされていないメタ文字は、トークンセパレータになります。

例えば、

$ echo "x"'y'\g
xyg

$ echo "<"'|'\>
<|>

$ echo x\; echo y
x; echo y

最初の例には、スペース区切り文字によって生成される2つのトークンがechoありxyzます。

2番目の例でも同様です。

第3の例ではセミコロンはエスケープので、スペース区切り文字によって生成される4つのトークンがあり、さechox;echo、およびy。最初のトークンはコマンドとして実行され、次の3つのトークンを入力として受け取ります。2番目echoは実行されないことに注意してください。


覚えておくべき重要なことは、そのbashの最初の文字をエスケープするためのルックス(ある'"\)し、そのためには、エスケープメタ文字の区切り文字を探します。

エスケープされない場合、これらの10個の特殊文字はtoken区切り文字として機能します。一部には追加の意味もありますが、何よりもまずトークン区切り文字です。


grepが期待するもの

grepの上記の例では、これらのトークンを必要としgrepstringfilename

質問の最初の試みは:

$ grep(then | there)xx

この場合()および|エスケープメタ文字であるので、これらのトークンへの入力を分割するのに役立つ:grep(then|there)、とx.x。grepが見たいgrepthen|therex.x

質問の2回目の試行は次のとおりです。

grep "(then | there)" xx

これはにトークン化しgrep(then|there)x.x。エコー用にgrepを交換すると、これを確認できます。

echo "(then | there)" xx
(その後| there)xx

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