A dobozomon található néhány adatbázis-kiírás egy Windows rendszerből. Ezek szöveges fájlok. A cygwint használom, hogy átnézhessem őket. Ezek egyszerű szöveges fájloknak tűnnek; olyan szövegszerkesztőkkel nyitom meg őket, mint a jegyzettömb és a wordpad, és olvashatónak tűnnek. Ha azonban a grep-et futtatom rajtuk, akkor az azt mondja: “2e88aa2f3b”>
.
Úgy vettem észre, hogy a fájlok tartalmaznak néhány ascii NUL
karaktert, amelyek véleményem szerint az adatbázis-kiindulási anyagból származnak.
Tehát mi okozza a grep-et bináris fájloknak? A NUL
karakter? Van-e egy zászló a fájlrendszeren? Mit kell változtatnom ahhoz, hogy a grep elérhesse mutasd nekem a soregyezéseket?
Megjegyzések
Válasz
Ha van NUL
karakter a fájl bármely pontján, a grep bináris fájlnak fogja tekinteni.
Ilyen megoldás lehet cat file | tr -d "\000" | yourgrep
a megszüntetés érdekében először null minden, és majd a fájlban való kereséshez.
Megjegyzések
- … vagy használja a
-a
/--text
, legalábbis a GNU grep használatával. - @derobert: Valójában néhány (régebbi) rendszeren a grep sorokat lát, de a kimenete az egyes illeszkedõ sorokat csonkolja elõször
NUL
(valószínűleg azért, mert C ‘ s printf-nek hívja, és megadja neki az egyező sort?). Ilyen rendszeren agrep cmd .sh_history
annyi üres sort ad vissza, ahány sor
cmd ‘, mivel az sh_history minden sorának van egy meghatározott formátuma,NUL
-vel az egyes sorok elején. (de a kommented ” legalábbis a GNU grep ” -ére valószínűleg valóra válik. Nem ‘ jelenleg nincs kéznél egy teszteléshez, de remélem, hogy ezt szépen kezelik)
grep
a cygwin-en binárisnak tekinthető, mert hosszú kötőjel (0x96) volt a helyett egy szokásos ASCII kötőjel / mínusz (0x2d). Gondolom, ez a válasz megoldotta az OP ‘ problémát, de úgy tűnik, hogy hiányos. Válasz
grep -a
nekem működött:
$ grep --help [...] -a, --text equivalent to --binary-files=text
megjegyzések
- Ez a legjobb, legolcsóbb válasz az IMO-ban.
- De nem POSIX-kompatibilis
- Szívesen elmagyaráznád, miért nem? Jó lenne egyértelművé tenni mindannyiunk számára, akik ezt a választ opciónak találjuk. Köszönöm :).
- Hé ‘ MÁSODIK alkalommal jöttem ide, hogy újra megtanuljam ezt a LOL-t. A szövegben egy francia akcentus (diakritikus) miatt a grep barf
Válasz
Használhatja a div id = “907fa53eca”>
segédprogram a szöveges tartalom kibontásához bármely fájlból, majd agrep
átvezetéshez, így:strings file | grep pattern
.
megjegyzések
- Ideális a részben sérült naplófájlok beolvasásához
- igen, néha bináris vegyes naplózás is megtörténik. Ez jó.
Válasz
GNU grep 2.24 RTFS
Következtetés: Csak 2 és 2 eset:
-
NUL
, plprintf "a\0" | grep "a"
-
kódolási hiba a C99 szerint
mbrlen()
, pl .:export LC_CTYPE="en_US.UTF-8" printf "a\x80" | grep "a"
mert
\x80
nem lehet egy UTF-8 Unicode-pont első bájtja: UTF-8 – Leírás | hu.wikipedia.org
Továbbá, amint azt Stéphane Chazelas említette Mi készteti a grep-t arra, hogy egy fájlt figyelembe vegyen legyen bináris? | Unix & Linux Stack Exchange , ezeket az ellenőrzéseket csak a TODO hosszú puffer első olvasatáig végzik.
Csak az első pufferig olvasható
Tehát ha NUL vagy kódolási hiba történik egy nagyon nagy fájl közepén, akkor előfordulhat, hogy mindenképpen meg kell greppelni.
Úgy gondolom, hogy ez teljesítmény okokból történik.
Például: ez kinyomtatja a sort:
printf "%10000000s\n\x80a" | grep "a"
, de ez nem így történik:
printf "%10s\n\x80a" | grep "a"
A puffer tényleges mérete a fájl olvasási módjától függ. Például.összehasonlítás:
export LC_CTYPE="en_US.UTF-8" (printf "\n\x80a") | grep "a" (printf "\n"; sleep 1; printf "\x80a") | grep "a"
A sleep
használatával az első sor átkerül a grepbe, még akkor is, ha csak 1 bájtos hosszú, mert a folyamat alvó állapotba kerül, és a második olvasás nem ellenőrzi, hogy a fájl bináris-e.
RTFS
git clone git://git.savannah.gnu.org/grep.git cd grep git checkout v2.24
Keresse meg a stderr hibaüzenet kódolását:
git grep "Binary file"
/src/grep.c
:
if (!out_quiet && (encoding_error_output || (0 <= nlines_first_null && nlines_first_null < nlines))) { printf (_("Binary file %s matches\n"), filename);
Ha ezeket a változókat jól megnevezték, akkor alapvetően a következtetésre jutottunk.
encoding_error_output
Gyors fogás a encoding_error_output
azt mutatja, hogy az egyetlen módosító kódút buf_has_encoding_errors
:
clen = mbrlen (p, buf + size - p, &mbs); if ((size_t) -2 <= clen) return true;
akkor csak man mbrlen
.
nlines_first_null és nlines
Inicializálva:
intmax_t nlines_first_null = -1; nlines = 0;
tehát ha nullát találnak, 0 <= nlines_first_null
igaz lesz.
TODO mikor nlines_first_null < nlines
valaha hamis? Lusta lettem.
POSIX
Nem határoz meg bináris opciókat grep – fájlminta keresése | pubs.opengroup.org , és a GNU grep nem dokumentálja, így az RTFS az egyetlen módja.
Megjegyzések
- Hatásos explikáció !
- Ne feledje, hogy az érvényes UTF-8 ellenőrzése csak az UTF-8 nyelveken történik. Vegye figyelembe azt is, hogy az ellenőrzést csak a fájlból olvasott első pufferen végzik, amely egy rendes fájl esetében 32768 bájtnak tűnik a rendszeremen, de egy cső vagy socket esetében akár egy bájt is lehet. A
(printf '\n\0y') | grep y
összehasonlítása például a(printf '\n'; sleep 1; printf '\0y') | grep y
-vel. - @St é phaneChazelas ” Ne feledje, hogy az érvényes UTF-8 ellenőrzése csak az UTF-8 lokalizációkban történik “: a
export LC_CTYPE='en_US.UTF-8'
mint az én példámban, vagy valami más? Buf read: csodálatos példa, hozzáadva a válaszhoz. Nyilvánvalóan jobban olvastad a forrást, mint én, emlékeztet arra a hacker koanra ” A hallgató felvilágosult ” 🙂 - Én sem néztem ‘ részletesen, de a közelmúltban
- @CiroSantilli 巴拿馬 文件 六四 事件 法轮功 a GNU grep melyik verziójával teszteltél?
Válasz
Az egyik szöveges fájlomat hirtelen binárisnak látta a grep:
$ file foo.txt foo.txt: ISO-8859 text
Megoldás az volt, hogy átalakítottam iconv
:
iconv -t UTF-8 -f ISO-8859-1 foo.txt > foo_new.txt
megjegyzések
- Ez velem is megtörtént. Különösen az oka egy ISO-8859-1 kódolású, nem törő szóköz volt, amelyet egy normál szóközzel kellett kicserélnem, hogy a grep megkaphassa a fájlban való keresést.
- a grep 2.21 kezeli az ISO-t -8859 szövegfájlokat, mintha binárisak lennének, adja hozzá az LC_ALL = C export exportot a grep parancs előtt.
- @netawater Köszönjük! Ez pl. az eset, ha van valami hasonló M ü ller szövegfájlban. Ez ‘ s
0xFC
hexadecimális, tehát a tartományon kívül a grep az utf8 esetében elvárható (legfeljebb0x7F
). Ellenőrizze a printf ‘ a \ x7F ‘ | grep ‘ a ‘ ahogy Ciro fent leírta.
Válasz
A (z) /etc/magic
vagy /usr/share/misc/magic
fájl olyan szekvenciákkal rendelkezik, amelyek a file
használja a fájltípus meghatározásához.
Megjegyzés , hogy a bináris csak egy tartalék megoldás lehet. Néha furcsa kódolású fájlokat is binárisnak tekintenek.
grep
Linux rendszeren van néhány lehetőség bináris fájlok kezelésére, például --binary-files
vagy -U / --binary
megjegyzések
- Pontosabban, kódolási hiba a C99 szerint ‘ s
mbrlen()
. Példa és forrásértelmezés: unix.stackexchange.com/a/276028/32558
Válasz
Egyik hallgatómmal volt ez a probléma. Van egy hiba a grep
fájlban a Cygwin
fájlban. Ha a fájl nem Ascii karakterekkel rendelkezik, grep
és egrep
binárisnak tekinti.
Megjegyzések
- Ez egy funkciónak hangzik, nem pedig hibának.Különösen, ha van egy parancssori opció a vezérléséhez (-a / –text)
Válasz
Valójában megválaszolva azt a kérdést, hogy “Mitől számít a grep egy fájl binárisnak?”, Használhatja a iconv
szót:
$ iconv < myfile.java iconv: (stdin):267:70: cannot convert
Az én esetemben voltak olyan spanyol karakterek, amelyek helyesen jelentek meg a szövegszerkesztőkben, de a grep binárisnak tekintette őket; A iconv
kimenet rámutatott e karakterek sor- és oszlopszámaira.
NUL
karakterek esetén iconv
normálisnak fogja tekinteni őket, és nem nyomtat ilyen típusú kimenetet, ezért ez a módszer nem megfelelő
Válasz
Ugyanez volt a problémám. A vi -b [filename]
elemet használtam a hozzáadott karakterek megtekintéséhez. Megtaláltam a vezérlő karaktereket: ^@
és ^M
. Ezután a vi mezőbe írja be a :1,$s/^@//g
parancsot a ^@
karakterek eltávolításához. Ismételje meg ezt a parancsot: ^M
.
Figyelem: A “kék” vezérlő karakterek megszerzéséhez nyomja meg a Ctrl + v gombot, majd a Ctrl + M
Válasz
Nekem is volt ilyen problémám, de az én esetemben egy illesztett sor túl hosszú.
file myfile.txt myfile.txt: UTF-8 Unicode text, with very long lines
grep
a teljes fájlt végigfuttatja sok mintával, de ha egy minta illeszkedik egy ” nagyon hosszú sor ” a Binary file myfile.txt matches
szóval állt le.
A -a
hozzáadása szintén megoldja ezt a problémát, de a NULL vagy más érvénytelen karakterek fájljának előzetes elemzése nem járna hatással (különben nincs ilyen, ha a grep más minták esetében nem teljes). Ebben az esetben a sértő sorban 25k + karakter volt!
Azért nem értem, miért történik ez csak akkor, amikor grep
megpróbálja visszaadni a sort, és nem akkor, amikor feldolgozza, és más mintákat keres.
--null-data
hasznosak lehetnek, haNUL
a határoló.