私はLinuxを学んでいますが、自分で解決できないように思える課題があります。ここにあります:
grepは、1行に4つの数字を含むが4以下のファイルから1行をgrepします。
私はこれにどのようにアプローチするかわかりません。特定の数値を検索することはできますが、文字列でその数値を検索することはできません。
\b\d{4}\b
私はLinuxを学んでいますが、自分で解決できないように思える課題があります。ここにあります:
grepは、1行に4つの数字を含むが4以下のファイルから1行をgrepします。
私はこれにどのようにアプローチするかわかりません。特定の数値を検索することはできますが、文字列でその数値を検索することはできません。
\b\d{4}\b
回答:
この質問を解釈する方法は2つあります。両方のケースに対処します。行を表示したい場合があります。
たとえば、(1)はを表示します1234a56789
が、(2)は表示しません。
それ自体が長い数字のシーケンスの一部ではない4桁のシーケンスを含むすべての行を表示する場合、1つの方法は次のとおりです。
grep -P '(?<!\d)\d{4}(?!\d)' file
これは、Ubuntu (GNU grep)がサポートするPerl正規表現を使用します。のようなテキストとは一致しませんし、その一部であるまたはにも一致しません。しかし、それはに一致します。grep
-P
12345
1234
2345
1234
1234a56789
Perlの正規表現では:
\d
は任意の数字を意味します([0-9]
またはを言う短い方法[[:digit:]]
です)。x{4}
x
4回一致します。({
}
構文はPerlの正規表現に固有のものではありません。拡張正規表現でgrep -E
も同様です。)ですから\d{4}
、と同じ\d\d\d\d
です。(?<!\d)
は、幅がゼロの負の後読みアサーションです。「\d
。が前にない限り」という意味です。(?!\d)
ゼロ幅の負の先読みアサーションです。「後に続く場合を除いて」を意味し\d
ます。(?<!\d)
また(?!\d)
、4桁のシーケンス外のテキストとは一致しません。代わりに、より長い一連の数字の一部である場合、(一緒に使用すると)4桁の数字が一致するのを防ぎます。
右端または左端の4桁のサブシーケンスがまだ一致するため、後読みのみまたは先読みのみを使用するだけでは不十分です。
後読みおよび先読みアサーションを使用する利点の1つは、パターンが周囲のテキストではなく、4桁のシーケンスのみと一致することです。これは、色の強調表示(--color
オプションを使用)を使用する場合に役立ちます。
ek@Io:~$ grep -P '(?<!\d)\d{4}(?!\d)' <<< 12345abc789d0123e4
12345abc789d0123e4
Ubuntuのデフォルトでは、各ユーザーのファイルにalias grep='grep --color=auto'
はがあり~.bashrc
ます。そのため、grep
(エイリアスが展開されるとき)で始まる単純なコマンドを実行すると、自動的に色が強調表示され、標準出力がターミナルになります(これがチェック対象です)。一致は通常、赤の色合い(朱色に近い)で強調表示されますが、斜体の太字で示しています。スクリーンショットは次のとおりです。--color=auto
またgrep
、行全体ではなく、一致するテキストのみを印刷することもできます-o
:
ek@Io:~$ grep -oP '(?<!\d)\d{4}(?!\d)' <<< 12345abc789d0123e4
0123
ただし、次の場合:
grep
サポートしていない-P
か、そうでない場合はPerlの正規表現を使用したくないし、そして...次に、代わりに拡張正規表現を使用してこれを実現できます。
grep -E '(^|[^0-9])[0-9]{4}($|[^0-9])' file
これは、それらを囲む4桁の数字と数字以外の文字(または行の先頭または末尾)に一致します。具体的には:
[0-9]
任意の数字(など[[:digit:]]
、または\d
Perlの正規表現)に一致し、{4}
「4回」を意味します。したがって[0-9]{4}
、4桁のシーケンスに一致します。[^0-9]
0
〜の範囲にない文字に一致し9
ます。[^[:digit:]]
(\D
Perlの正規表現では)と同等です。^
、[
]
かっこで囲まれていない場合、行の先頭に一致します。同様に$
、行末に一致します。|
手段または括弧は(代数のように)グループ化されています。したがって(^|[^0-9])
、行の先頭または数字以外の文字と($|[^0-9])
一致し、行の末尾または数字以外の文字と一致します。したがって、一致[0-9]{4}
は、同時に4桁のシーケンス()を含む行でのみ発生します。
(^|[^0-9])
)、及び($|[^0-9])
)が続きます。一方、4桁のシーケンスを含むすべての行を表示したいが、4桁を超えるシーケンスを含まない場合(4桁のみの別のシーケンスとは別のものでも)、概念的には目標は、あるパターンに一致するが別のパターンには一致しない行を見つけることです。
したがって、1つのパターンでそれを行う方法を知っていても、2つのパターンを別々に使用して、マットの 2番目の提案のようなものを使用することをお勧めしますgrep
。
Perlの正規表現の高度な機能を使用する場合、それを行う際に大きなメリットは得られないため、使用しないほうがよい場合があります。しかし、上記のスタイルに合わせて、以下の代わりに(およびブレース)を使用したmattのソリューションの短縮版を次に示し\d
ます[0-9]
。
grep -P '\d{4}' file | grep -Pv '\d{5}'
を使用しているため[0-9]
、mattの方法はより移植性が高く、grep
Perlの正規表現をサポートしていないシステムで動作します。の代わりに[0-9]
(または[[:digit:]]
)\d
を使用し{
}
、を使用し続けると、マットの方法の移植性がもう少し簡潔になります。
grep -E '[0-9]{4}' file | grep -Ev '[0-9]{5}'
あなたが本当にgrep
コマンドを好む場合
grep
、パイプで区切られた2 つではありません)...次に使用できます:
grep -Px '(\d{0,4}\D)*\d{4}(\D\d{0,4})*' file
この-x
フラグはgrep
、行全体が一致する行のみを表示します(一致を含む行ではなく)。
Perlの正規表現を使用したのは、この場合の簡潔さ\d
と\D
実質的な明瞭さが向上するからです。ただし、grep
サポートしていないシステムに移植可能なものが必要な-P
場合は、それらを[0-9]
and [^0-9]
(または[[:digit:]]
and [^[:digit]]
)に置き換えることができます。
grep -Ex '([0-9]{0,4}[^0-9])*[0-9]{4}([^0-9][0-9]{0,4})*' file
これらの正規表現の機能は次のとおりです。
中央、\d{4}
または[0-9]{4}
4桁の1つのシーケンスに一致します。これらは複数ある場合もありますが、少なくとも1つ必要です。
左側、(\d{0,4}\D)*
または4桁以下の非数字が続く([0-9]{0,4}[^0-9])*
0個以上の(*
)インスタンスに一致します。ゼロ桁(つまり、何もない)は、「4桁以下」の可能性の1つです。これはマッチ()空の文字列または(b)の任意の文字列終了非数字で以上4桁の任意の配列を含みません。
中央\d{4}
(または[0-9]{4}
)のすぐ左のテキストは空か、数字以外で終わる必要があるため、中央のすぐ左に\d{4}
別の(5番目の)数字がある4桁と一致しないようにします。
右側、(\D\d{0,4})*
または非数字の([^0-9][0-9]{0,4})*
ゼロ個以上(*
)に一致し、その後に4桁以下の数字が続きます(前と同様に、4、3、2、1、またはまったくない場合もあります)。このマッチ()空の文字列または(b)の任意の文字列から始まる数字以外にし、4桁以上の任意のシーケンスを含みません。
中央\d{4}
(または[0-9]{4}
)のすぐ右のテキストは空にするか、数字以外で始まる必要があるため、中央のすぐ右に\d{4}
別の(5番目の)数字がある4桁と一致しないようにします。
これにより、4桁のシーケンスがどこかに存在し、5桁以上のシーケンスがどこにも存在しないことが保証されます。
この方法で行うことは悪くも間違っていません。しかし、おそらくこの代替案を検討する最も重要な理由は、上記およびmattの回答で示唆されているように、代わりに(または同様の)使用の利点を明確にすることです。grep -P '\d{4}' file | grep -Pv '\d{5}'
そのようにして、あなたの目標は、あるものを含むが別のものを含まない行を選択することであることは明らかです。さらに、構文は単純です(そのため、多くの読者/保守者がより早く理解できるかもしれません)。
これにより、4つの数字が連続して表示されますが、それ以上は表示されません
grep '[0-9][0-9][0-9][0-9][^0-9]' file
^は意味しないことに注意してください
これには問題がありますが、修正方法がわかりません...番号が行末であれば、表示されません。
ただし、このいバージョンはその場合に機能します
grep '[0-9][0-9][0-9][0-9]' file | grep -v [0-9][0-9][0-9][0-9][0-9]
a12345b
一致するため、見つけ2345b
ます。
grep
perlの正規表現をサポートしていない場合(-P
)、次のシェルコマンドを使用します。
grep -w "$(printf '[0-9]%.0s' {1..4})" file
どこでprintf '[0-9]%.0s' {1..4}
4回生産し[0-9]
ます。この方法は、長い数字があり、パターンを繰り返したくない場合に便利です(4
探している数字の数に置き換えるだけです)。
を使用-w
すると、単語全体が検索されます。ただし、などの英数字の文字列に興味がある場合は、パターンの最後に1234a
追加[^0-9]
します。たとえば、
grep "$(printf '[0-9]%.0s' {1..4})[^0-9]" file
使用$()
は基本的にコマンドの置換です。この投稿をチェックしてprintf
、パターンがどのように繰り返されるかを確認してください。
1234a12345
表示する必要がありますか?