bashスクリプトでunicodeをgrepする方法


10
if grep -q "�" out.txt
    then
        echo "working"
    else
        cat out.txt
fi

基本的に、ファイル「out.txt」にファイル内のどこかに「 」が含まれている場合は、「機能」をエコーし​​たい場合、およびファイル「out.txt」にファイル内のどこにも「 」が含まれていない場合は、 cat out.txtに

編集:これが私がやっていることです。私はopenssl復号化をブルートフォースにしようとしています。

openssl encは、成功すると0を返し、それ以外の場合はゼロ以外を返します。注:AES / CBCはパディングを正しく行うことに基づいて「復号化が機能する」かどうかしか判断できないため、誤検知が発生します。したがって、ファイルは復号化されますが、正しいパスワードではないため、意味不明なものになります。意味不明な言葉の一般的な文字は「 」です。したがって、出力に「 」が含まれている場合は、doループを続行する必要があります。

Heres my git link https://github.com/Raphaeangelo/OpenSSLCracker Heres the script

while read line
do
openssl aes-256-cbc -d -a -in $1 -pass pass:$line -out out.txt 2>out.txt >/dev/null && printf "==================================================\n"
if grep -q "�" out.txt
    then
        :
    else
        cat out.txt &&
            printf "\n==================================================" &&
            printfn"\npassword is $line\n" &&
            read -p "press return key to continue..." < /dev/tty; 
fi
done < ./password.txt

その中に 文字が含まれた出力がまだ表示されています

更新:解決済み

printf "Working..."

while read line
do
openssl aes-256-cbc -d -a -in $1 -pass pass:$line -out out.txt 2>out.txt >/dev/null
if file out.txt | grep -q 'out.txt: ASCII text'
    then
        printf "\n==================================================\n\n" &&
            cat out.txt &&
            printf "\n==================================================" &&
            printf "\npassword is $line\n" && 
            read -p "press return key to continue..." < /dev/tty;
    else
        : 
fi
done < ./password.txt

それは正しいように見え、動作するはずです(ところで、私はあなたのユニコード文字を表示するためのフォントを持っていませんが、特別な意味を持つものはありません)。grepユニコードを長く理解します(これにより処理が非常に遅くなるため、ASCII文字列を検索するために、a LANG=C grepはパフォーマンスが大幅に向上します)。
peterh-モニカを2018年

私はこれを削除して別の質問を投稿する必要があるかもしれません。なぜなら、私はここにいる全員を完全に混乱させていると確信しているからです。
スチュアートスローン

@スチュアートスローンあなたの質問のタイトルHow to grep for unicode � in a bash scriptはこれが本当にあなたが欲しいものですか?ユニコードを抽出するには?私たちが助けることができるように明確にしてください!

1
@Goro元の投稿を編集しました。私はそれが理にかなっていると思います。そうでない場合はお知らせください。明確化を試みます。
スチュアートスローン

1
現在の両方の答えは非常に誤解を招くものです。(もう一度)私の答えを読んでください、私はそれを編集して両方の答えが間違っていることを説明しました。
アイザック

回答:


27

grep 仕事のための間違ったツールです。

が表示されるのU+FFFD REPLACEMENT CHARACTERは、それが文字通りファイルの内容に含まれているからではなく、テキストベースの入力のみを処理することになっているツールでバイナリファイルを調べたからです。無効な入力(つまり、ランダムなバイナリデータ)を処理する標準的な方法は、現在のロケール(ほとんどの場合UTF-8)で無効なものをすべて画面に表示する前にU + FFFDに置き換えることです。

つまり、リテラル\xEF\xBF\xBD(U + FFFD文字のUTF-8バイトシーケンス)がファイル内で発生することはほとんどありません。grepあなたに言うことは完全に正しいです、何もありません。

ファイルに不明なバイナリが含まれているかどうかを検出する1つの方法は、file(1)次のコマンドを使用することです。

$ head -c 100 /dev/urandom > rubbish.bin
$ file rubbish.bin
rubbish.bin: data

不明なファイルタイプの場合は、単にと表示されますdata。やってみる

$ file out.txt | grep '^out.txt: data$'

ファイルに実際に任意のバイナリが含まれているかどうか、したがってゴミの可能性が最も高いかどうかを確認します。

これがout.txtUTF-8でエンコードされたテキストファイルのみであることを確認する場合は、代わりに次のコマンドを使用できますiconv

$ iconv -f utf-8 -t utf-16 out.txt >/dev/null

あなたはまさに正しいです!残念ながら、出力にはまだ(以前より少ない)ゴミが残っています。
スチュアートスローン

fileこれらのファイルの他のコンテンツタイプを検出する可能性があります。100%が常にUTF-8でエンコードされたテキストファイルのみを期待しているiconv場合、ファイルが有効なUTF-8であるかどうかをで確認できますiconv -f utf-8 -t utf-16 out.txt >/dev/nulliconv無効なUTF-8シーケンスのためにファイルを変換できない場合は、ゼロ以外の終了コードで戻ります。
Boldewyn 2018年

2
ファイルコマンドは正しかった!あなたは私の問題を解決するのを助けてくれてありがとう!
スチュアートスローン

4
もちろん、そのgrepは「仕事のためのツール」ですgrep -axv '.*' badchars.txt。これにより、無効なUnicode文字を含む行が出力されます。
Isaac、

1
これは非常に誤解を招く恐れがあります。何をするかについて私の回答を読んくださいfile
アイザック

5

TL; DR:

grep -axv '.*' out.txt 

長い答え

現在の回答はどちらも非常に誤解を招きやすく、基本的に間違っています。

テストするには、次の2つのファイルを入手してください(非常に評価の高い開発者:Markus Kuhnから):

$ wget https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-demo.txt
$ wget https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt

デモ

1つ目UTF-8-demo.txtは、UTF-8が多くの言語、数学、点字、その他多くの便利な種類の文字をどれだけうまく表示できるかを示すために設計されたファイルです。(utf-8を理解している)テキストエディターで見てみると、多くの例が表示され、は表示されません

1つの答えが提案するテスト:文字範囲を制限すると、\x00-\x7Fこのファイル内のほとんどすべてが拒否されます。
それは非常に間違っており、そのファイルには何もないので削除されません

その回答で推奨されているテストを使用する72.5 %と、ファイルが削除されます。

$ grep -oP "[^\x00-\x7F]" UTF-8-demo.txt | tr -d '\n' | wc -c
10192
$ cat UTF-8-demo.txt | wc -c
14058

これは(ほとんどの実用的な目的では)ファイル全体です。完全に有効な文字を表示するように非常によく設計されたファイル。

テスト

2番目のファイルは、いくつかの境界ケースを試行して、utf-8リーダーが適切に機能していることを確認するように設計されています。「 」が表示される原因となる多くの文字が内部に含まれています。しかし、使用する他の回答の推奨(選択されたもの)はfile、このファイルでは著しく失敗します。ゼロバイト(\0)(技術的には有効なASCII)と\x7fバイト(DEL-削除)(明らかにASCII文字)を削除するだけで、すべてのファイルがfileコマンドに対して有効になります。

$ cat UTF-8-test.txt | tr -d '\0\177' > a.txt
$ file a.txt 
a.txt: Non-ISO extended-ASCII text, with LF, NEL line terminators

file多くの不正な文字を検出できないだけでなく、UTF-8エンコードファイルであることを検出して報告することもできません。

そしてはい、fileUTF-8でエンコードされたテキストを検出して報告できます。

$ echo "ééakjfhhjhfakjfhfhaéá" | file -
/dev/stdin: UTF-8 Unicode text

また、file1〜31の範囲のほとんどの制御文字をASCIIとして報告できません。file一部の範囲は次のように報告されます()data

$ printf '%b' "$(printf '\\U%x' {1..6})" | file -
/dev/stdin: data

その他ASCII text

$ printf '%b' "$(printf '\\U%x' 7 {9..12})" | file -
/dev/stdin: ASCII text

印刷可能な文字範囲として(改行付き):

$ printf '%b' "$(printf '\\U%x' {32..126} 10)" | file -
/dev/stdin: ASCII text

しかし、いくつかの範囲は奇妙な結果を引き起こす可能性があります:

$ printf '%b' "$(printf '\\U%x' {14..26})" | file -
/dev/stdin: Atari MSA archive data, 4113 sectors per track, starting track: 5141, ending track: 5655

プログラムfileはテキストを検出するためのツールではなく、実行可能なプログラムまたはファイル内のマジックナンバーを検出するためのツールです。

範囲がfile検出し、私が見つけた対応するタイプは次のとおりでした:

  • 1バイト値、主にascii:

    {1..6} {14..26} {28..31} 127   :data
    {128..132} {134..159}          :Non-ISO extended-ASCII text
    133                            :ASCII text, with LF, NEL line terminators
    27                             :ASCII text, with escape sequences
    13                             :ASCII text, with CR, LF line terminators
    8                              :ASCII text, with overstriking
    7 {9..12} {32..126}            :ASCII text
    {160..255}                     :ISO-8859 text
    
  • UTF-8でエンコードされた範囲:

    {1..6} {14..26} {28..31} 127   :data
    27                             :ASCII text, with escape sequences
    13                             :ASCII text, with CR, LF line terminators
    8                              :ASCII text, with overstriking
    7 {9..12} {32..126}            :ASCII text
    {128..132} {134..159}          :UTF-8 Unicode text
    133                            :UTF-8 Unicode text, with LF, NEL line terminators
    {160..255}                     :UTF-8 Unicode text
    {256..5120}                    :UTF-8 Unicode text
    

考えられる解決策の1つは以下のとおりです。


以前の回答。

投稿する文字のUnicode値は次のとおりです。

$ printf '%x\n' "'�"
fffd

はい、それはUnicode文字「置換文字」(U + FFFD)です。これは、テキストで見つかった無効な Unicode文字を置き換えるために使用される文字です。それは「視覚的な助け」であり、本物のキャラクターではありません。無効なUNICODE文字を含むすべての行を見つけてリストするには、次のようにします。

grep -axv '.*' out.txt 

ただし、無効な文字があるかどうかを検出するだけの場合は、次を使用します。

grep -qaxv '.*' out.txt; echo $?

結果が1ファイルがクリーンである場合、それ以外の場合はゼロになります0


あなたが求めていたのが:文字を見つける方法だったら、これを使ってください:

➤ a='Basically, if the file "out.txt" contains "�" anywhere in the file I'
➤ echo "$a" | grep -oP $(printf %b \\Ufffd)
�

または、システムがUTF-8テキストを正しく処理する場合は、次のようにします。

➤ echo "$a" | grep -oP '�'
�

よろしくお願いしますgrep -axv '.*' !! テキストファイルのいくつかの不良文字と、それらをemacsで修正する方法に10年か2年悩んでいます!!!
nealmcb

3

この非常に早い答えは元の投稿に対するものでした:

bashスクリプトでunicodeをgrepする方法

if grep -q "�" out.txt
    then
        echo "working"
    else
        cat out.txt  fi

基本的に、ファイル「out.txt」にファイル内のどこかに「 」が含まれている場合は、「機能」をエコーし​​たい場合、およびファイル「out.txt」にファイル内のどこにも「 」が含まれていない場合は、 cat out.txtに

やってみる

grep -oP "[^\x00-\x7F]"

if .. then次のようなステートメントで:

if grep -oP "[^\x00-\x7F]" file.txt; then
    echo "grep found something ..."
else
    echo "Nothing found!"
fi

説明💡:

  • -P--perl-regexp:PATTERNはPerl正規表現です
  • -o--only-matching:PATTERNに一致する行の部分のみを表示します
  • [^\x00-\x7F] 単一の非ASCII文字に一致する正規表現です。
  • [[:ascii:]] -単一のASCII文字に一致します
  • [^[:ascii:]] -単一の非ASCII文字と一致します

bash

LC_COLLATE=C grep -o '[^ -~]' file

3
これは、誰かが英語を話さなくなるとすぐに
Kevin

あるいは、誰かがアラカルト、絵文字、ポケモン、または厳密に7ビットASCIIに限定されていない何かについて議論しようとした場合。09 0A 0D(タブ、ラインフィード、キャリッジリターン)を除いて、00-1Fで何でも探してください。
Alcaro

これは非常に悪い考えです。これにより、ASCII範囲を超える有効なUnicode文字が拒否されます。有効な文字は100万個を少し超えるだけです。すごい。試してください:printf '%b' "$(printf '\\U%x' {128..131})" | grep -oP "[^\x00-\x7F]"コードが拒否する4つの有効なUnicode文字。:-(
アイザック

これは非常に誤解を招く答えです。ASCIIのみに制限する単純なアプローチが大幅に失敗する理由を私の回答で読んください。
アイザック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.