再帰的grepは、一部のファイルからの一致をリストしません

Aug 20 2020

私はGNUgrep 3.4を使用して、特定のパターンを含むスクリプトを見つけています。このために、私はそのgrepように再帰的に呼び出します

grep -rin . -e "pattern" 

パターンは単なる単語であり、正規表現ではありません。奇妙なことに、出力には、文字列が確実に含まれている一部のファイルのオカレンスがリストされていません。

これらのファイルを開いて、を使用しvimて検索してみたところ/pattern、パターンが見つかりました。エンコーディングはvimとして表示され[dos:utf-8:]ます。この行をコピーして新しいファイルに書き込むと、上記のgrepコマンドで正しく一覧表示されます。

grep元のファイルがリストされないのはなぜですか?

回答

1 RedGrittyBrick Aug 20 2020 at 20:08

Grep(または少なくとも古いもの)はUTF8を理解していません。したがって、構成された文字、ハイフネーションポイント、またはその他の非表示のデータは、grepを思いとどまらせる可能性があります。

Grepは、の値の影響も受けます。 $LC_ALL, $LC_CTYPEおよび$ LANG。

vimを使用して、grepが見つけられなかった単語の前後の数行を保存してから、その小さなサンプルファイルの16進ダンプを作成します。grepが失敗した理由がわかるでしょう

また、(vimのコマンドを使用することができgag8文字を検討するなど)が、進ダンプが明確になることがあり

1 buddemat Aug 20 2020 at 22:28

私は問題を見つけました(別の答えの助けを借りて)。ファイル 'grep'はutf-8、実際にはエンコードされていませんが、の出力を表示しませんでしたutf-16be。私はhexdump(@RedGrittyBrickへのクレジット)を使用してこれを学びました:

hd file_for_which_grep_works_as_expected.txt

降伏

00000000  20 20 20 20 50 61 74 74  65 72 6e 0a              |    Pattern.|
0000000c

一方、

hd file_for_which_grep_fails.txt

戻ってきた

00000000  fe ff 00 50 00 61 00 74  00 74 00 65 00 72 00 6e  |...P.a.t.t.e.r.n|
00000010  00 0a                                             |..|
00000012

したがって、エンコーディングを再確認します

file -i file_for_which_grep_fails.txt

として識別しましたtext/plain; charset=utf-16be

utf-8によって示されているのvimが実際にはファイルエンコーディングではなくバッファエンコーディングであることを認識できませんでした。実行中でも、正しく表示され(ここで見つけます:set fileencodingvimfileencoding=utf-16https://superuser.com/a/28783/1210682)。

したがって、問題は、エンコードされたファイルでgrep動作しないことutf-16です。これはすでにここで説明されています:https://superuser.com/a/231471/1210682。ただし、変換の救済utf-16にファイルをutf-8前にgrep、私はとすることができるファイルは事前に知っていないと私は、再帰的にそれを使用する場合の作業はしていませんutf-8し、これutf-16とたくさんのファイルを検索しています。

さまざまな解決策がありますが、そのうちの2つをここで簡単に説明します。

  1. 私のために働いた手っ取り早い解決策は、utf-16バージョンに一致するものを含むように検索パターンを拡張し、両方のパターンの1つを検索することでした。

    grep -riPa . -e "pattern|p.a.t.t.e.r.n."
    

    もちろん、これは可能なパターンの点で非常に制限されています。

  2. greplikeugrepまたはripgrep(とりわけ)utf-16ファイルを処理できる代替手段があります。ripgrep18.04以降の標準のUbuntuパッケージリポジトリで利用できるものを使用することになりました。

    rg -i "pattern"  
    

ここに代替案に関する素晴らしい議論があります: https://stackoverflow.com/questions/3752913/grepping-binary-files-and-utf16、その中で、検索パターンをに変換し、utf-16それをにフィードしようとする興味深いアプローチgrep。しかし、私はそれを動作させることができませんでした。