megjegyzések
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 aexec
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 agrep -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
ésgrep -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 ' tfor 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 *
Defor 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)
321
abar
helyett: – D