Come richiedere unicode in uno script bash


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

Fondamentalmente, se il file "out.txt" contiene " " in qualsiasi parte del file, vorrei che riecheggiasse "funzionante" E se il file "out.txt" NON contiene " " in qualsiasi punto del file, allora vorrei a cat out.txt

EDIT: Quindi ecco cosa sto facendo. Sto cercando di forzare una decrittografia di openssl.

openssl enc restituisce 0 in caso di successo, altrimenti diverso da zero. Nota: otterrai falsi positivi perché AES / CBC può solo determinare se "funziona la decodifica" in base al corretto riempimento. Quindi il file viene decrittografato, ma non sarà la password corretta, quindi sarà gibberish. Un personaggio comune nel gibberish è " ". Quindi voglio che il ciclo do continui se l'output contiene " ".

Ecco il mio link git https://github.com/Raphaeangelo/OpenSSLCracker Ecco lo 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

mi sta ancora mostrando un output con il carattere in esso contenuto

AGGIORNAMENTO: risolto

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

Sembra corretto, dovrebbe funzionare (a proposito, non ho caratteri che il tuo personaggio Unicode possa vedere, ma nessuno di essi ha un significato speciale). grepa lungo capisce unicode (che lo rende molto più lento, quindi per cercare stringhe ASCII, a LANG=C grepè un enorme miglioramento delle prestazioni).
Peter - Ripristina Monica l'

Potrei doverlo eliminare e pubblicare un'altra domanda perché sono sicuro di confondere completamente tutti qui.
Stuart Sloan,

@Stuart Sloan il titolo della tua domanda How to grep for unicode � in a bash scriptè questo è davvero quello che vuoi? estrarre l'unicode? per favore chiarisci in modo che possiamo aiutarti!

1
@Goro Ho apportato la modifica al mio post originale. Spero abbia senso. Per favore fatemi sapere se non funziona e cercherò di chiarire.
Stuart Sloan,

1
Entrambe le risposte attuali sono estremamente fuorvianti. Per favore leggi (di nuovo) la mia risposta , l'ho modificata per spiegare che entrambe le risposte sono errate.
Isaac,

Risposte:


27

grep è lo strumento sbagliato per il lavoro.

Si vede U+FFFD REPLACEMENT CHARACTERnon perché è letteralmente nel contenuto del file, ma perché hai guardato un file binario con uno strumento che dovrebbe gestire solo input basato su testo. Il modo standard di gestire input non validi (cioè dati binari casuali) è sostituire tutto ciò che non è valido nella locale corrente (molto probabilmente UTF-8) con U + FFFD prima che colpisca lo schermo.

Ciò significa che è molto probabile che un letterale \xEF\xBF\xBD(la sequenza di byte UTF-8 per il carattere U + FFFD) non si verifichi mai nel file. grepha perfettamente ragione nel dirtelo, non ce n'è.

Un modo per rilevare se un file contiene un binario sconosciuto è con il file(1)comando:

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

Per qualsiasi tipo di file sconosciuto dirà semplicemente data. Provare

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

per verificare se il file contiene davvero qualsiasi binario arbitrario e quindi molto probabilmente spazzatura.

Se vuoi assicurarti che out.txtsia solo un file di testo con codifica UTF-8, puoi alternativamente usare iconv:

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

Hai esattamente ragione! purtroppo, sto ancora ricevendo un po '(meno di prima) immondizia nell'output.
Stuart Sloan,

fileRileva forse qualche altro tipo di contenuto per quei file. Se il 100% sempre aspetta solo UTF-8 file di testo codificati, è possibile controllare con iconv, se un file è valido UTF-8: iconv -f utf-8 -t utf-16 out.txt >/dev/null. Se iconvnon è possibile convertire il file a causa di sequenze UTF-8 non valide, verrà restituito con un codice di uscita diverso da zero.
Boldewyn,

2
Il comando file era giusto! Mi hai aiutato a risolvere il mio problema grazie!
Stuart Sloan,

4
Naturalmente grep "è lo strumento per il lavoro", prova grep -axv '.*' badchars.txt. Ciò stamperà qualsiasi riga che contiene caratteri Unicode non validi .
Isacco,

1
Questo è estremamente fuorviante, per favore leggi nella mia risposta cosa filefa.
Isaac,

5

TL; DR:

grep -axv '.*' out.txt 

risposta lunga

Entrambe le risposte presenti sono estremamente fuorvianti e sostanzialmente sbagliate.

Per testare, scarica questi due file (da uno sviluppatore molto apprezzato: 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

dimostrazione

Il primo UTF-8-demo.txtè un file progettato per mostrare quanto UTF-8 sia in grado di presentare molte lingue, matematica, braille e molti altri utili tipi di caratteri. Dai un'occhiata con un editor di testo (che capisce utf-8) e vedrai molti esempi e no .

Il test che una risposta propone: limitare la gamma di caratteri \x00-\x7Frifiuterà quasi tutto all'interno di questo file.
Questo è molto sbagliato e non ne rimuoverà nessuno perché non ce n'è nel file .

L'utilizzo del test consigliato in quella risposta rimuoverà 72.5 %il file:

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

Questo è (per la maggior parte degli scopi pratici) l'intero file. Un file molto ben progettato per mostrare caratteri perfettamente validi.

Test

Il secondo file è progettato per provare diversi casi limite per confermare che i lettori utf-8 stanno facendo un buon lavoro. Contiene al suo interno molti caratteri che causano la visualizzazione di un ' '. Ma l'altra raccomandazione di risposta (quella selezionata) da utilizzare filenon ha esito positivo con questo file. Rimuovere solo un byte zero ( \0) (che tecnicamente è valido ASCII) e un \x7fbyte (DEL - cancella) (che è chiaramente anche un carattere ASCII) renderà valido tutto il file per il filecomando:

$ 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

Non solo non fileriesce a rilevare i molti caratteri errati, ma non riesce anche a rilevare e segnalare che si tratta di un file codificato UTF-8.

E sì, fileè in grado di rilevare e segnalare il testo codificato UTF-8:

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

Inoltre, filenon riesce a riportare come ASCII la maggior parte dei caratteri di controllo nell'intervallo da 1 a 31. ( file) riporta alcuni intervalli come data:

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

Altri come ASCII text:

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

Come intervallo di caratteri stampabile (con nuove righe):

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

Ma alcuni intervalli possono causare risultati strani:

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

Il programma filenon è uno strumento per rilevare il testo, ma per rilevare numeri magici in programmi o file eseguibili.

Gli intervalli filerilevati e il tipo corrispondente riportato che ho trovato erano:

  • Valori di un byte, principalmente 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
    
  • Intervalli codificati 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
    

Una possibile soluzione è la seguente.


Risposta precedente

Il valore Unicode per il personaggio che stai postando è:

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

Sì, si tratta di un carattere Unicode 'REPLACEMENT CHARACTER' (U + FFFD) . Questo è un carattere usato per sostituire qualsiasi carattere Unicode non valido trovato nel testo. È un "aiuto visivo", non un vero personaggio. Per trovare ed elencare ogni riga completa che contiene caratteri UNICODE non validi , utilizzare:

grep -axv '.*' out.txt 

ma se vuoi rilevare solo se un personaggio non è valido, usa:

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

Se il risultato è che 1il file è pulito, altrimenti sarà zero 0.


Se quello che stavi chiedendo era: come trovare il personaggio, usa questo:

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

O se il tuo sistema elabora correttamente il testo UTF-8, semplicemente:

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

OMG grazie mille per grep -axv '.*' !! Ho lottato con alcuni personaggi cattivi nei miei file di testo e come risolverli in emacs, per un decennio o due !!!
nealmcb,

3

Questa prima risposta è stata per il post originale che era:

Come richiedere unicode in uno script bash

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

Fondamentalmente, se il file "out.txt" contiene " " in qualsiasi parte del file, vorrei che riecheggiasse "funzionante" E se il file "out.txt" NON contiene " " in qualsiasi punto del file, allora vorrei a cat out.txt

Provare

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

con una if .. thendichiarazione come segue:

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

Explanation💡:

  • -P, --perl-regexp: PATTERN è un'espressione regolare Perl
  • -o, --only-matching: mostra solo la parte di una riga corrispondente a PATTERN
  • [^\x00-\x7F] è una regex per abbinare un singolo carattere non ASCII.
  • [[:ascii:]] - corrisponde a un singolo carattere ASCII
  • [^[:ascii:]] - corrisponde a un singolo carattere non ASCII

nel bash

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

3
Questo si spezzerà (hanno un falso positivo) non appena qualcuno non parla inglese ...
Kevin,

o se qualcuno prova a discutere di à la carte, emoji, Pokémon o qualsiasi altra cosa non strettamente limitata a ASCII a 7 bit. Meglio cercare qualsiasi cosa in 00-1F, tranne 09 0A 0D (scheda, avanzamento riga, ritorno a capo).
Alcaro,

Questa è una pessima idea. Ciò rifiuterà qualsiasi carattere Unicode valido al di sopra dell'intervallo ASCII, solo poco più di un milione di caratteri validi. Sorprendente. Prova: printf '%b' "$(printf '\\U%x' {128..131})" | grep -oP "[^\x00-\x7F]"solo 4 caratteri Unicode validi che il tuo codice rifiuta. :-(
Isaac,

Questa è una risposta estremamente fuorviante. Per favore leggi nella mia risposta perché l'approccio semplicistico di limitare solo all'ASCII fallisce gravemente.
Isaac,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.