Jak mogę grep dla wszystkich znaków spoza ASCII?
Mam kilka bardzo dużych plików XML i próbuję znaleźć linie, które zawierają znaki inne niż ASCII. Próbowałem:
grep -e "[\x{00FF}-\x{FFFF}]" file.xml
Ale to zwraca każdą linię w pliku, niezależnie od tego, czy linia zawiera znak w określonym zakresie.
Czy źle zrozumiałam składnię, czy robię coś innego? Też próbowałem:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(z pojedynczymi i podwójnymi cudzysłowami otaczającymi wzór).
10 answers
Możesz użyć polecenia:
grep --color='auto' -P -n "[\x80-\xFF]" file.xml
To da ci numer linii i podświetli znaki inne niż ascii na Czerwono.
W niektórych systemach, w zależności od twoich ustawień, powyższe nie zadziała, więc możesz grepować przez odwrotność
grep --color='auto' -P -n "[^\x00-\x7F]" file.xml
Zauważ również, że ważnym bitem jest znacznik -P
, który odpowiada --perl-regexp
: więc będzie interpretował Twój wzorzec jako wyrażenie regularne Perla. Mówi również, że
Jest to wysoce eksperymentalne i grep-P może ostrzegać przed unimplemented funkcje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 14:54:33
Zamiast zakładać zakres bajtów znaków nie-ASCII, jak większość powyższych rozwiązań, IMO jest nieco lepiej, IMO, aby być wyraźnym co do rzeczywistego zakresu bajtów znaków ASCII.
Więc pierwszym rozwiązaniem będzie np.:
grep --color='auto' -P -n '[^\x00-\x7F]' file.xml
(który w zasadzie greps dla dowolnego znaku spoza zakresu ASCII w systemie szesnastkowym: od \x00 do \x7f)
Na Mountain Lion, który nie działa (z powodu braku wsparcia PCRE w BSD grep) , ale z pcre
zainstalowanym za pomocą Homebrew, następujące rzeczy będą działać równie dobrze:
pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml
Jakieś plusy i minusy, które każdy może wymyślić?Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-04 12:25:41
Dla mnie działa:
grep -P "[\x80-\xFF]" file.xml
Znaki inne niż ASCII zaczynają się od 0x80 i przechodzą do 0xFF, gdy patrząc na bajty. Grep (i rodzina) nie przetwarza Unicode, aby scalić wielbajtowe znaki w jeden obiekt w celu dopasowania wyrażeń regularnych, jak chcesz. Opcja -P
w moim grepie pozwala na użycie ucieczki \xdd
w klasach znaków, aby osiągnąć to, co chcesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-08 21:59:22
W Perlu
perl -ane '{ if(m/[[:^ascii:]]/) { print } }' fileName > newFile
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-10 14:05:58
Najprostszym sposobem jest zdefiniowanie znaku nie-ASCII... jako znak, który nie jest znakiem ASCII.
LC_ALL=C grep '[^ -~]' file.xml
Dodaj zakładkę po ^
w razie potrzeby.
Ustawienie LC_COLLATE=C
pozwala uniknąć przykrych niespodzianek dotyczących znaczenia zakresów znaków w wielu lokalizacjach. Ustawienie LC_CTYPE=C
jest konieczne do dopasowania znaków jednobajtowych - w przeciwnym razie polecenie pominie niepoprawne sekwencje bajtów w bieżącym kodowaniu. Ustawienie LC_ALL=C
pozwala całkowicie uniknąć efektów zależnych od ustawień lokalnych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-15 13:03:04
Oto kolejny wariant, który dał całkowicie Inne wyniki wyszukiwania grep dla [\x80-\xFF]
w zaakceptowanej odpowiedzi. Być może przyda się komuś znalezienie dodatkowych znaków nie-ascii:
grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt
Uwaga: mój komputer grep (Mac) nie miał opcji -P
, więc zrobiłem brew install grep
i rozpocząłem powyższe wywołanie od ggrep
zamiast grep
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-23 17:00:21
Działa następujący kod:
find /tmp | perl -ne 'print if /[^[:ascii:]]/'
Zastąp /tmp
nazwą katalogu, który chcesz przeszukać.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-13 23:02:41
O dziwo, musiałem to zrobić dzisiaj! Skończyło się na użyciu Perla, ponieważ nie mogłem uruchomić grep/egrep (nawet w trybie-P). Coś w stylu:
cat blah | perl -en '/\xCA\xFE\xBA\xBE/ && print "found"'
Dla znaków unicode (jak \u2212
w przykładzie poniżej) użyj tego:
find . ... -exec perl -CA -e '$ARGV = @ARGV[0]; open IN, $ARGV; binmode(IN, ":utf8"); binmode(STDOUT, ":utf8"); while (<IN>) { next unless /\N{U+2212}/; print "$ARGV: $&: $_"; exit }' '{}' \;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-16 12:51:39
Wyszukiwanie znaków niedrukowalnych.
Zgadzam się z Harvey powyżej Zakopane w komentarzach, często bardziej przydatne jest wyszukiwanie znaków niedrukowalnych lub łatwo jest myśleć nie-ASCII, kiedy naprawdę powinieneś myśleć nie-drukowalne. Harvey sugeruje "użyj tego: "[^\N -~]". Dodaj \r dla plików tekstowych DOS. To tłumaczy się na "[^\x0a\x020 -\x07e] "i dodaje \x0d dla CR"
Ponadto, dodanie -c (Pokaż liczbę dopasowanych wzorców) do grepa jest przydatne, gdy wyszukiwanie niedrukowalnych znaków jako dopasowanych łańcuchów może zepsuć terminal.
Znalazłem dodanie zakresu 0-8 i 0x0e-0x1f (do zakresu 0x80 - 0xff) jest użytecznym wzorcem. Nie dotyczy to tabulatorów, CR i LF oraz jednego lub dwóch innych nietypowych znaków drukowalnych. Więc IMHO całkiem przydatnym (choć prymitywnym) wzorem grepa jest ten:
grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *
Podział:
\x00-\x08 - non-printable control chars 0 - 7 decimal
\x0E-\x1F - more non-printable control chars 14 - 31 decimal
\x80-1xFF - non-printable chars > 128 decimal
-c - print count of matching lines instead of lines
-P - perl style regexps
Instead of -c you may prefer to use -n (and optionally -b) or -l
-n, --line-number
-b, --byte-offset
-l, --files-with-matches
Np. praktyczny przykład użycia find do grepowania wszystkich plików w bieżącym katalogu:
find . -type f -exec grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" {} +
Możesz chcieć dostosować czasami grep. np. znak BS(0x08 - backspace) używany w niektórych plikach do druku lub do wykluczenia VT (0x0b-vertical tab). Znaki BEL(0X07) i ESC (0X1B) mogą być również uważane za drukowalne w niektórych przypadkach.
Non-Printable ASCII Chars ** marks PRINTABLE but CONTROL chars that is useful to exclude sometimes Dec Hex Ctrl Char description Dec Hex Ctrl Char description 0 00 ^@ NULL 16 10 ^P DATA LINK ESCAPE (DLE) 1 01 ^A START OF HEADING (SOH) 17 11 ^Q DEVICE CONTROL 1 (DC1) 2 02 ^B START OF TEXT (STX) 18 12 ^R DEVICE CONTROL 2 (DC2) 3 03 ^C END OF TEXT (ETX) 19 13 ^S DEVICE CONTROL 3 (DC3) 4 04 ^D END OF TRANSMISSION (EOT) 20 14 ^T DEVICE CONTROL 4 (DC4) 5 05 ^E END OF QUERY (ENQ) 21 15 ^U NEGATIVE ACKNOWLEDGEMENT (NAK) 6 06 ^F ACKNOWLEDGE (ACK) 22 16 ^V SYNCHRONIZE (SYN) 7 07 ^G BEEP (BEL) 23 17 ^W END OF TRANSMISSION BLOCK (ETB) 8 08 ^H BACKSPACE (BS)** 24 18 ^X CANCEL (CAN) 9 09 ^I HORIZONTAL TAB (HT)** 25 19 ^Y END OF MEDIUM (EM) 10 0A ^J LINE FEED (LF)** 26 1A ^Z SUBSTITUTE (SUB) 11 0B ^K VERTICAL TAB (VT)** 27 1B ^[ ESCAPE (ESC) 12 0C ^L FF (FORM FEED)** 28 1C ^\ FILE SEPARATOR (FS) RIGHT ARROW 13 0D ^M CR (CARRIAGE RETURN)** 29 1D ^] GROUP SEPARATOR (GS) LEFT ARROW 14 0E ^N SO (SHIFT OUT) 30 1E ^^ RECORD SEPARATOR (RS) UP ARROW 15 0F ^O SI (SHIFT IN) 31 1F ^_ UNIT SEPARATOR (US) DOWN ARROW
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-21 12:42:27
Może być interesujące wiedzieć, jak wyszukać jeden znak unicode. To polecenie może pomóc. Musisz tylko znać kod w UTF8
grep -v $'\u200d'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-13 23:19:11