再帰的grepは、一部のファイルからの一致をリストしません
私はGNUgrep 3.4を使用して、特定のパターンを含むスクリプトを見つけています。このために、私はそのgrep
ように再帰的に呼び出します
grep -rin . -e "pattern"
パターンは単なる単語であり、正規表現ではありません。奇妙なことに、出力には、文字列が確実に含まれている一部のファイルのオカレンスがリストされていません。
これらのファイルを開いて、を使用しvim
て検索してみたところ/pattern
、パターンが見つかりました。エンコーディングはvim
として表示され[dos:utf-8:]
ます。この行をコピーして新しいファイルに書き込むと、上記のgrep
コマンドで正しく一覧表示されます。
grep
元のファイルがリストされないのはなぜですか?
回答
Grep(または少なくとも古いもの)はUTF8を理解していません。したがって、構成された文字、ハイフネーションポイント、またはその他の非表示のデータは、grepを思いとどまらせる可能性があります。
Grepは、の値の影響も受けます。 $LC_ALL, $LC_CTYPEおよび$ LANG。
vimを使用して、grepが見つけられなかった単語の前後の数行を保存してから、その小さなサンプルファイルの16進ダンプを作成します。grepが失敗した理由がわかるでしょう
また、(vimのコマンドを使用することができga
、g8
文字を検討するなど)が、進ダンプが明確になることがあり
私は問題を見つけました(別の答えの助けを借りて)。ファイル '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 fileencoding
vim
fileencoding=utf-16
https://superuser.com/a/28783/1210682)。
したがって、問題は、エンコードされたファイルでgrep
動作しないことutf-16
です。これはすでにここで説明されています:https://superuser.com/a/231471/1210682。ただし、変換の救済utf-16
にファイルをutf-8
前にgrep
、私はとすることができるファイルは事前に知っていないと私は、再帰的にそれを使用する場合の作業はしていませんutf-8
し、これutf-16
とたくさんのファイルを検索しています。
さまざまな解決策がありますが、そのうちの2つをここで簡単に説明します。
私のために働いた手っ取り早い解決策は、
utf-16
バージョンに一致するものを含むように検索パターンを拡張し、両方のパターンの1つを検索することでした。grep -riPa . -e "pattern|p.a.t.t.e.r.n."
もちろん、これは可能なパターンの点で非常に制限されています。
grep
likeugrep
またはripgrep
(とりわけ)utf-16
ファイルを処理できる代替手段があります。ripgrep
18.04以降の標準のUbuntuパッケージリポジトリで利用できるものを使用することになりました。rg -i "pattern"
ここに代替案に関する素晴らしい議論があります: https://stackoverflow.com/questions/3752913/grepping-binary-files-and-utf16、その中で、検索パターンをに変換し、utf-16
それをにフィードしようとする興味深いアプローチgrep
。しかし、私はそれを動作させることができませんでした。