Bir bash betiğinde unicode nasıl grep


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

Temel olarak, "out.txt" dosya " " dosyada herhangi bir yerde içeriyorsa ben "çalışma" yankı istiyorum VE "out.txt" dosya " " dosyada hiçbir yerde içermezse o zaman istiyorum out.txt için kedi

EDIT: İşte yaptığım şey. Ben bir openssl şifresini çözmek için kaba kaba çalışıyorum.

openssl enc başarı durumunda 0 döndürür, aksi takdirde sıfırdan farklıdır. Not: yanlış pozitifler alacaksınız çünkü AES / CBC, "doğru şifre çözme işleminin doğru yapılmasına" dayanarak "şifre çözmenin işe yarayıp yaramadığını" belirleyebilir. Böylece dosya şifresi çözülür, ancak doğru şifre olmayacaktır, bu yüzden içinde anlamsız olacaktır. Anlamsızca kullanılan ortak bir karakter " " dir. Bu yüzden çıktı " " içeriyorsa do döngüsünün devam etmesini istiyorum.

Heres benim git link https://github.com/Raphaeangelo/OpenSSLCracker Heres betiği

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

hala içinde charicter ile çıktı gösteriyor

GÜNCELLEME: Çözüldü

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

Doğru görünüyor, işe yaramalı (btw, unicode karakterinizin görmesi için yazı tipim yok, ancak hiçbirinin özel bir anlamı yok). grepuzun unicode anlar (bu çok daha yavaş yapar, bu yüzden ascii dizeleri aramak için LANG=C grep, a büyük bir performans iyileştirmedir).
peterh - Monica'yı eski durumuna getir

Bunu silmek ve başka bir soru göndermek zorunda kalabilirim çünkü eminim ki burada herkesi tamamen karıştırıyorum.
Stuart Sloan

@Stuart Sloan sorunuzun başlığı How to grep for unicode � in a bash scriptbu gerçekten istediğiniz şey mi? unicode çıkarmak için? yardımcı olabilmemiz için lütfen açıklayınız!

1
@ Goro Düzenlemeyi orijinal yazımda yaptım. Umarım mantıklıdır. Lütfen bunu yapmazsanız bana bildirin ve netleştirmeye çalışacağım.
Stuart Sloan

1
Her iki cevap da son derece yanıltıcıdır. Lütfen cevabımı tekrar okuyun , her iki cevapta da yanlış olduğunu açıklamak için düzenledim.
Isaac

Yanıtlar:


27

grep iş için yanlış araçtır.

harfini U+FFFD REPLACEMENT CHARACTERtam anlamıyla dosya içeriğinde olduğu için değil, yalnızca metin tabanlı girdiyi işlemesi gereken bir araçla ikili bir dosyaya baktığınız için görürsünüz. Geçersiz girişi (yani rastgele ikili veriler) işlemenin standart yolu, geçerli yerel ayarda (büyük olasılıkla UTF-8) geçerli olmayan her şeyi ekrana vurmadan önce U + FFFD ile değiştirmektir.

Bu \xEF\xBF\xBD, dosyada bir değişmezin (U + FFFD karakteri için UTF-8 bayt dizisi) hiçbir zaman oluşmadığı anlamına gelir. grepsize söylemede tamamen haklı, hiçbiri yok.

Bir dosyanın bilinmeyen bir ikili dosya içerip içermediğini tespit etmenin bir yolu şu file(1)komuttur:

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

Herhangi bir bilinmeyen dosya türü için söyleyecektir data. Deneyin

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

dosyanın gerçekten herhangi bir ikili ikili içerip içermediğini ve dolayısıyla büyük olasılıkla çöp olup olmadığını kontrol etmek için.

Bunun out.txtyalnızca UTF-8 kodlu bir metin dosyası olduğundan emin olmak istiyorsanız, alternatif olarak aşağıdakileri kullanabilirsiniz iconv:

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

Kesinlikle haklısın! ne yazık ki, çıktıda hala (eskisinden daha az) çöp alıyorum.
Stuart Sloan

Muhtemelen filebu dosyalar için başka içerik türünü algılar. % 100 her zaman yalnızca UTF-8 kodlu metin dosyaları bekliyorsanız, sen ile kontrol edebilirsiniz iconvbir dosyanın geçerli UTF-8 ise,: iconv -f utf-8 -t utf-16 out.txt >/dev/null. Eğer iconvnedeniyle geçersiz UTF-8 dizileri için dosyayı dönüştürmek olamaz, bu bir sıfır olmayan çıkış kodu ile dönecektir.
Boldewyn

2
Dosya komutu doğru! Sorunumu çözmeme yardımcı oldun teşekkürler!
Stuart Sloan

4
Tabii ki grep "iş için bir araçtır", deneyin grep -axv '.*' badchars.txt. Bu, geçersiz Unicode Karakteri içeren tüm satırları yazdırır .
Isaac

1
Bu son derece yanıltıcı, lütfen ne yaptığımla ilgili cevabımı okuyun file.
Isaac

5

TL; DR:

grep -axv '.*' out.txt 

uzun cevap

Her iki mevcut cevap da son derece yanıltıcı ve temel olarak yanlıştır.

Test etmek için, bu iki dosyayı alın (çok saygın bir geliştiriciden: 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

gösteri

Birincisi UTF-8-demo.txt, UTF-8'in birçok dil, matematik, braille ve diğer birçok yararlı karakter türünü ne kadar iyi sunabileceğini göstermek için tasarlanmış bir dosyadır. Bir metin düzenleyicisine bir göz atın (utf-8'i anlayan) ve birçok örnek göreceksiniz ve hayır .

Yanıtın önerdiği test: karakter aralığını sınırlamak \x00-\x7Fbu dosyadaki hemen hemen her şeyi reddedecektir.
Bu çok yanlış ve bu dosyada hiçbiri olmadığı için hiçbirini kaldırmayacak .

Bu cevapta önerilen testi kullanmak 72.5 %dosyanın kaldırılmasını sağlayacaktır :

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

Bu (en pratik amaçlar için) tüm dosyadır. Mükemmel geçerli karakterleri göstermek için çok iyi tasarlanmış bir dosya.

Ölçek

İkinci dosya utf-8 okuyucularının iyi bir iş çıkardığını doğrulamak için çeşitli sınır durumlarını denemek üzere tasarlanmıştır. İçinde bir ' ' gösterilmesine neden olacak birçok karakter içeriyor. Ancak, kullanılacak diğer yanıt önerisi (seçilen) filebu dosyayla büyük ölçüde başarısız olur. Yalnızca sıfır bayt ( \0) (teknik olarak geçerli ASCII olan) ve bir \x7fbayt (DEL - delete) (açıkça ASCII karakteridir ) kaldırılması tüm dosyayı filekomut için geçerli hale getirir :

$ 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

Sadece gelmez filealgılamak için başarısız birçok yanlış karakterler, aynı zamanda bir UTF-8 kodlanmış dosya olduğunu tespit ve rapor için başarısız.

Ve evet, fileUTF-8 kodlu metni algılayabilir ve raporlayabilir:

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

Ayrıca, file1 ila 31 aralığındaki kontrol karakterlerinin çoğunun ASCII olarak rapor verememesi. ( file) Bazı aralıkları şöyle bildirir data:

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

Diğerleri ASCII text:

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

Yazdırılabilir karakter aralığı olarak (yeni satırlarla):

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

Ancak bazı aralıklar tuhaf sonuçlara neden olabilir:

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

Program filemetni algılamak için bir araç değil , yürütülebilir programlarda veya dosyalarda sihirli sayıları algılamak için bir araçtır .

Aralıkları filealgılar ve bulduğum bildirilen karşılık gelen tip:

  • Bir bayt değerleri, çoğunlukla 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 kodlu aralıklar:

    {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
    

Olası bir çözüm aşağıda yatıyor.


Önceki Yanıt.

Gönderdiğiniz karakterin Unicode değeri:

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

Evet, bu bir Unicode Karakter 'DEĞİŞTİRME KARAKTERİ' (U + FFFD) . Bu, metinde bulunan geçersiz Unicode karakterlerin yerine geçmek için kullanılan bir karakterdir . Gerçek bir karakter değil, bir "görsel yardım" dır. Geçersiz UNICODE karakterleri içeren tüm satırları bulmak ve listelemek için şunu kullanın:

grep -axv '.*' out.txt 

ancak yalnızca herhangi bir karakterin geçersiz olup olmadığını tespit etmek istiyorsanız, şunu kullanın:

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

Sonuç 1dosya temizse, aksi takdirde sıfır olur 0.


Sorduğunuz şey şuysa: karakteri nasıl bulacağınız , o zaman şunu kullanın:

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

Veya sisteminiz UTF-8 metnini doğru bir şekilde işliyorsa, basitçe:

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

OMG için çok teşekkür ederim grep -axv '.*' !! Metin dosyalarımda birkaç kötü karakterle ve on yıl veya iki on yıl boyunca emac'larda nasıl düzeltileceğiyle mücadele ettim!
nealmcb

3

Bu çok erken cevap orijinal yazı içindi:

Bir bash betiğinde unicode nasıl grep

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

Temel olarak, "out.txt" dosya " " dosyada herhangi bir yerde içeriyorsa ben "çalışma" yankı istiyorum VE "out.txt" dosya " " dosyada hiçbir yerde içermezse o zaman istiyorum out.txt için kedi

Deneyin

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

if .. thenaşağıdaki gibi bir ifade ile :

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

Explanation💡:

  • -P, --perl-regexp: PATTERN bir Perl düzenli ifadesidir
  • -o, --only-matching: satırın PATTERN ile eşleşen kısmını göster
  • [^\x00-\x7F] ASCII olmayan tek bir karakterle eşleşecek bir normal ifade.
  • [[:ascii:]] - tek bir ASCII karakteriyle eşleşir
  • [^[:ascii:]] - tek bir ASCII olmayan karakterle eşleşir

içinde bash

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

3
Birisi İngilizce konuşmaz konuşmaz kırılacak (yanlış bir pozitif olacak) ...
Kevin

veya birisi alakart, emoji, Pokémon veya kesinlikle 7bit ASCII ile sınırlı olmayan herhangi bir şeyi tartışmaya çalışırsa. 09 0A 0D (sekme, satır besleme, satır başı) hariç 00-1F'de daha iyi bir şey arayın.
Alcaro

Bu çok kötü bir fikir. Bu , ASCII aralığının üzerindeki herhangi bir geçerli Unicode karakterini reddedecektir , sadece bir milyondan fazla geçerli karakterden biraz daha fazla. İnanılmaz. Deneyin: printf '%b' "$(printf '\\U%x' {128..131})" | grep -oP "[^\x00-\x7F]"Kodunuzun reddettiği 4 geçerli Unicode karakter. :-(
Isaac

Bu son derece yanıltıcı bir cevap. Lütfen okuyun cevabım sadece ASCII için sınırlamanın basit yaklaşım fena halde başarısız neden.
Isaac
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.