A kérdésre itt már vannak válaszok :

megjegyzések

  • mit értesz " által az egyes karakterláncok teljes részével "? Nem ' nem akarja, hogy az egész sort kinyomtassa?
  • Meg tudná erősíteni, hogy azt szeretné, hogy az egyező fájlok tartalmazzák mind a " foo " és " 321 ", de nem csak " foo " vagy csak " 321 "?
  • Tetszik, hogy ' s 321 a bar helyett: – D

Válasz

GNU grep

Kicsit gyorsabbnak kell lennie, mert a második grep működhet a fájlok listáján.

grep -lZ "foo" * | xargs -0 grep -l "321" 

POSIX grep kereséssel

find hasznosabb, ha rekurzív könyvtárakban akar keresni (ebben az esetben elveszíti a -mindepth és -maxdepth opciók.

find . -mindepth 1 -maxdepth 1 -type f -exec grep -q "foo" {} \; -exec grep -l "321" {} + 

Megjegyzések

  • -r jól működött az első grep esetében, hogy ez a GNU megoldás számomra rekurzív legyen, ahelyett, hogy a POSIX sort használná mindazokkal a exec s

Válasz

Ezt egy rövid szkript segítségével teheti meg:

for FILE in * do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE done 

Ezt egy soron is megteheti:

for FILE in *; do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE; done 

grep 0 (true) értéket ad vissza, ha megtalálta a karakterláncot, és a parancsokat elválasztó && azt jelenti, hogy a második csak akkor fut, ha az első igaz volt. A -q beállítás biztosítja, hogy a grep nem ad ki semmit.

Az echo csak akkor fut, ha mindkét karakterlánc megtalálható ugyanabban a fájlban.


Más módot gondoltam rá. Ez valószínűleg hatékonyabb lesz, ha a kérdéses fájlok nagyobbak, mint a telepített RAM, mivel csak egyszer kell grep végigvinni az egyes fájlokat.

 for FILE in * do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE done 

és az egysoros verzió:

 for FILE in *; do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE; done 

megjegyzések

  • A hatékonyabb megoldás érdekében: Mi van akkor, ha a fájl " foo foo " van benne?
  • Ez ' s mire való a uniq | sort | uniq. " foo foo " végül egy sor lesz, de " foo 321 " végül két sor, mert a grep -o az összes megtalált karakterláncot külön vonalakon adja ki, még akkor is, ha ugyanazon a vonalon kezdődtek.
  • Ha a fájlok olyan hatalmasak lesznek, hogy rendben lenne fájlonként legalább hatszor elágazni, akkor valószínűleg van értelme az awk helyett használni, hogy a fájlokat ne kelljen a végéig keresni.
  • @Ladadadada kapott azt. 🙂
  • @HaukeLaging grep -q és grep -l nem keres a fájl végéig: azonnal kilépnek mivel találnak egyezést. Kíváncsi vagyok, miért nem az első megoldás ' t for FILE in *; do grep -q foo "$FILE" && grep -l 321 "$FILE"; done

miért válaszol

Furcsa. Számomra mindkét változat működik (grep (GNU grep) 2.13):

grep "foo\|321" grep -E "foo|321" 

1 – csak mindkét egyezéssel rendelkező fájlok megjelenítése

A for file in * válasz működik, de teljesítményrémálommá válhat (nagy mennyiségű fájl esetén) ): fájlonként legalább két folyamat. Ez gyorsabb (a GNU világában):

find . -type f -print0 | xargs -0 -r grep --files-with-matches --null -- string1 | xargs -0 -r grep --files-with-matches -- string2 

A string1 legyen az, amely kevesebb találatot eredményez.

Megjegyzések

  • A kérdező csak akkor keresi az eredményt, hogy igaz legyen, ha egy fájl mindkét karakterláncot tartalmazza, nem pedig csak egyezik legalább egy
  • tetszik --files-with-matches opció. Csak olvassa fel a man oldalon, és a grep leáll, miután megtalálja az első egyezést, ami azt jelenti, hogy ' nagyon hatékony nagy fájlok esetén, ha a mérkőzés korán megtörténik. Azt is mondja, hogy a rövid opciót -l a POSIX határozza meg, így a GNU világon kívül is használható.
  • @Ladadadada A hatékonyság nem jelent előnyt -q mégis. A GNU megemlítésével nem ' nem a -file-with-match-ekre gondoltam, hanem a -0 / –ull-ra.Ami most eszembe jut: az útvonalnév kibővítése alfabetikus rendezést tartalmaz (nagyon rossz: úgy tűnik, hogy ezt még ' sem lehet kikapcsolni), így hatalmas fájlok esetén még a for file in * valóban nem szórakoztató.
  • Valójában a hatékonyság optimalizálása néhány nagy fájl esetében egészen más lenne, mint a sok kicsi és * csak nem fog működni pár ezer fájl után.
  • @Ladadadada Ez nem lenne ' t egy külső parancs parancssorának részeként működik: grep foo * De for file in * egy shell belső struktúra, ezért feltételezem, hogy hogy a parancssori korlát itt nem alkalmazható.

Válasz

Alapvetően az összes fájl megkeresése, beleértve egy adott karakterláncot egy könyvtárban, használhatja:

grep -lir "pattern" /path/to/the/dir 
  • -l: ennek a szkennelésnek a végrehajtására leáll az első meccsen
  • -i: figyelmen kívül hagyja a kis- és nagybetűk megkülönböztetését a mintában és a beviteli fájlokban egyaránt
  • -r: az összes fájl keresése a könyvtár alatt, rekurzívan

Két minta kereséséhez próbálja ki ezt:

grep -lr "321" $(grep -lr "foo" /path/to/the/dir) 

Megjegyzések

  • A szokásos unalmas megjegyzések a $() szóval kapcsolatban nem alkalmazzák a szóközöket. A gyakorlatban egy vonalhéjnál a shellnél ez a parancs jól fog működni.

Válasz

grep -e "foo" -e "321" * 

Az -e használata több mintához

SZERKESZTÉS

Abban az esetben, ha mindkettőnek meg kell egyeznie:

grep -e ".*foo.*321.*" * 

Ha a sorrend nem számít:

grep -e ".*foo.*321.*" ".*321.*foo.*" * 

Megjegyzések

  • Ez nem ad választ a kérdésre. Ha kritikát szeretne kérni vagy magyarázatot szeretne kérni egy szerzőtől, hagyjon megjegyzést a bejegyzés alatt.
  • @mdpc azt hiszem, ez választ ad. Mi készteti másképp gondolkodásra?
  • @HaukeLaging Mert visszatér, ha bármelyik minta egyezik. Az OP olyan esetet keres, ahol csak akkor tér vissza igazra, ha mindkettő megtalálható a fájlban.
  • Megértésem szerint ez csak azokat a fájlokat találja meg, ahol mindkét karakterlánc ugyanazon a soron található (I ne ' ne gondolja. alapértelmezés szerint egyezik az új sorokkal)

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