TL; DR:
grep -axv '.*' out.txt
długa odpowiedź
Obie obecne odpowiedzi są bardzo mylące i zasadniczo błędne.
Aby przetestować, pobierz te dwa pliki (od bardzo dobrze uznanego programisty: Markusa Kuhna):
$ 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
Próbny
Pierwszy UTF-8-demo.txt
to plik zaprojektowany, aby pokazać, jak dobrze UTF-8 jest w stanie przedstawić wiele języków, matematykę, alfabet Braille'a i wiele innych przydatnych typów znaków. Spójrz za pomocą edytora tekstu (który rozumie utf-8), a zobaczysz wiele przykładów i nie �
.
Test zaproponowany przez jedną odpowiedź: ograniczenie zakresu znaków do \x00-\x7F
odrzucenia prawie wszystkiego w tym pliku.
To bardzo źle i nie usunie żadnego, �
ponieważ nie ma go w tym pliku .
Zastosowanie testu zalecanego w tej odpowiedzi spowoduje usunięcie 72.5 %
pliku:
$ grep -oP "[^\x00-\x7F]" UTF-8-demo.txt | tr -d '\n' | wc -c
10192
$ cat UTF-8-demo.txt | wc -c
14058
To jest (dla najbardziej praktycznych celów) cały plik. Plik bardzo dobrze zaprojektowany, aby wyświetlać idealnie poprawne znaki.
Test
Drugi plik ma na celu wypróbowanie kilku przypadków granicznych w celu potwierdzenia, że czytniki utf-8 wykonują dobrą robotę. Zawiera wiele znaków, które powodują wyświetlenie znaku . Ale druga rekomendacja odpowiedzi (wybrana) file
zawodzi rażąco z tym plikiem. Tylko usunięcie zerowego bajtu ( \0
) (który technicznie jest poprawny ASCII) i \x7f
bajtu (DEL - usuń) (który oczywiście jest również znakiem ASCII) sprawi, że cały plik będzie ważny dla file
polecenia:
$ 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
Nie tylko nie file
wykrywa wielu niepoprawnych znaków, ale także nie wykrywa i nie zgłasza, że jest to plik zakodowany w UTF-8.
I tak, file
jest w stanie wykryć i zgłosić tekst zakodowany w UTF-8:
$ echo "ééakjfhhjhfakjfhfhaéá" | file -
/dev/stdin: UTF-8 Unicode text
Ponadto file
nie zgłasza jako ASCII większości znaków kontrolnych z zakresu od 1 do 31. file
Zgłasza niektóre zakresy jako data
:
$ printf '%b' "$(printf '\\U%x' {1..6})" | file -
/dev/stdin: data
Inne jako ASCII text
:
$ printf '%b' "$(printf '\\U%x' 7 {9..12})" | file -
/dev/stdin: ASCII text
Jako zakres znaków do wydruku (z nowymi liniami):
$ printf '%b' "$(printf '\\U%x' {32..126} 10)" | file -
/dev/stdin: ASCII text
Ale niektóre zakresy mogą powodować dziwne wyniki:
$ 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 file
nie jest narzędziem do wykrywania tekstu, ale do wykrywania magicznych liczb w wykonywalnych programach lub plikach.
Wykryto zakresy file
i odpowiedni typ zgłoszony przeze mnie znaleziony to:
Wartości jednobajtowe, głównie 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
Zakodowane zakresy 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
Jedno z możliwych rozwiązań znajduje się poniżej.
Poprzednia odpowiedź.
Wartość Unicode publikowanego znaku to:
$ printf '%x\n' "'�"
fffd
Tak, jest to znak Unicode „ZMIANA WYMIANY” (U + FFFD) . Jest to znak używany do zastąpienia dowolnego nieprawidłowego znaku Unicode znalezionego w tekście. To „pomoc wizualna”, a nie prawdziwa postać. Aby znaleźć i wyświetlić każdą pełną linię zawierającą nieprawidłowe znaki UNICODE, użyj:
grep -axv '.*' out.txt
ale jeśli chcesz tylko wykryć, czy jakiś znak jest nieprawidłowy, użyj:
grep -qaxv '.*' out.txt; echo $?
Jeśli wynikiem jest to, 1
że plik jest czysty, w przeciwnym razie wyniesie zero 0
.
Jeśli pytałeś: jak znaleźć �
postać, użyj tego:
➤ a='Basically, if the file "out.txt" contains "�" anywhere in the file I'
➤ echo "$a" | grep -oP $(printf %b \\Ufffd)
�
Lub jeśli twój system poprawnie przetwarza tekst UTF-8, po prostu:
➤ echo "$a" | grep -oP '�'
�
grep
długo rozumie Unicode (co czyni go znacznie wolniejszym, więc wyszukiwanie ciągów asciiLANG=C grep
jest ogromną poprawą wydajności).