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

  • --null-data hasznosak lehetnek, ha NUL a határoló.

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 a grep 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)

  • A NUL karakter jelenléte az egyetlen kritérium? Kétlem. ‘ valószínűleg ennél okosabb. Bármi, ami az Ascii 32-126 tartományon kívül esik, az én tippem lenne, de ‘ nekünk meg kell vizsgálnunk a forráskódot, hogy biztosak legyünk benne.
  • a konkrét grep példány man oldaláról. A megvalósítással kapcsolatos megjegyzésed érvényes, a forrás megdönti a dokumentumokat.
  • Volt egy fájlom, amely 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, pl printf "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ó (legfeljebb 0x7F). 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

    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 vagy Ctrl + @ . Ezután mentse és lépjen ki a vi-ből.

    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.

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük