web-dev-qa-db-ja.com

「単語」を構成する文字を「grep-w」に伝える方法は?

$ printf 'asf .test. afd\nasaf foo-test asfdads\n'
asf .test. afd
asaf foo-test asfdads

$ printf 'asf .test. afd\nasaf foo-test asfdads\n' | grep -w test
asf .test. afd
asaf foo-test asfdads

質問:「foo-test」と一致させるにはどうすればよいですか?より正確に言うと、「-w」は「-」を区切り文字として使用しますが、「。」は使用しないでください

つまり、grepに、.wordsを構成する文字の中にあり、Word borderがないことを伝えることができますか。 .testの間に?

または、grep以外のソリューションはありますか?

2.19より前のバージョンでは、GNU grep's -wは1バイト文字の英数字とアンダースコアのみを考慮します(したがって、UTF-8ロケールでは、26 + 26のみ) + 10 + 1(ASCII文字、数字、アンダースコア))を単語の構成要素として使用します。たとえば、echo Stéphane | grep -w Stは一致します。これは2.19で修正されました。

ただし、ロジックは手動で実装できます。

 grep -E '([^[:alnum:]_.]|^)test([^[:alnum:]_.]|$)'

つまり、testの前に、単語以外の構成要素または行の先頭があり、その後に単語以外の構成要素または行の終わりが続きます。

(上記の[:alnum:]は、ロケール内の数字と文字に一致します。ASCIIのものだけでなく、ASCIIのもののみ)が必要な場合は、ロケールをCに修正してください) 。

Word以外の構成要素を取り巻くものを一致に含めたくない場合(たとえば、GNUの-oを使用しているため)、今回はPCRE正規表現とルックアラウンド演算子を使用できます。

grep -Po '(*UCP)(?<![\w.])test(?![\w.])'

(*UCP)を削除し、LC_ALL=Cを追加して、ASCII文字と数字のみに一致するようにします。

正規表現の先頭で(*UCP)を使用すると、PCREライブラリに̲niC̲odeP̲roperties\wに使用する必要があることが通知されます。

これがないと、\wはロケールの英数字とアンダースコアに一致しますが、シングルバイト文字の場合のみです。これは、ASCIIのものだけが一致するUTF-8ロケール(現在の標準)では機能しません。(*UCP)はUTF-8でも機能します。一致します。ロケールとは異なる可能性のあるPCRE独自の文字プロパティの概念に基づいていますが、GNUシステムでは、UTF-8ロケール定義と同様に、不完全で古くなっています(少なくとも2015-04の)。

10