Szeretném elérni, hogy a több mintázat megfeleljen az implicit ÉS minták között, azaz egyenértékű több grep futtatásával egy sorozatban:
grep pattern1 | grep pattern2 | ...
Tehát hogyan lehet átalakítani ilyesmire?
grep pattern1 & pattern2 & pattern3
Szeretnék egyetlen grep-et használni, mert dinamikusan építem az argumentumokat, ezért mindennek egy karakterláncba kell illeszkednie. A szűrő használata a rendszer jellemzője, nem a grep, tehát nem érv érte.
Ne keverje össze ezt a kérdést:
grep "pattern1\|pattern2\|..."
Ez egy VAGY több mintás egyezés.
Megjegyzések
Válasz
agrep
ezzel a szintaxissal teheti meg:
agrep "pattern1;pattern2"
GNU-val grep
, ha w épült A PCRE támogatással megteheti:
grep -P "^(?=.*pattern1)(?=.*pattern2)"
A ast grep
:
grep -X ".*pattern1.*&.*pattern2.*"
(.*
s hozzáadása megegyezik a <x>
és <y>
pontosan , soha nem egyezik, mivel nincs olyan karakterlánc, amely lehet mind a
, mind a b
egyidejűleg).
Ha a minták nem fedik egymást, akkor ezt is megteheti:
grep -e "pattern1.*pattern2" -e "pattern2.*pattern1"
A legjobb hordozható módszer valószínűleg a awk
használatával történik, amint azt már említettük:
awk "/pattern1/ && /pattern2/"
sed
:
sed -e "/pattern1/!d" -e "/pattern2/!d"
Vigyázzon, hogy mindezeknek más a reguláris kifejezés szintaxisa.
Megjegyzések
- A
agrep
szintaxis nem működik én … melyik verziót vezették be? - @Raman 2.04 1992-től már megvolt. Nincs ‘ okom azt hinni, hogy a kezdetektől fogva nem volt ott ‘. A
agrep
újabb verziói (1992 után) megtalálhatók a glimpse / webglimpse csomagban. Esetleg más megvalósítása van. Az ast-grep verzióval kapcsolatban hibám volt, a kiterjesztett regexps opció-X
, nem pedig-A
. - @St é phaneChazelas Köszönöm,
agrep
0.8.0 van a Fedora 23-on. Ez úgy tűnik, hogy legyen másagrep
, mint amire hivatkozol. - @Raman, a tiéd úgy hangzik, hogy TRE
agrep
. - @Techiee, vagy csak
awk '/p1/ && /p2/ {n++}; END {print 0+n}'
Válasz
Nem adta meg a grep verziót, ez fontos. Egyes regexp motorok lehetővé teszik a többszörös egyezést ÉS csoportosításával az “& “, de ez nem szabványos és nem hordozható szolgáltatás. De legalább a GNU grep nem támogatja ezt.
Az OTOH egyszerűen helyettesítheti a grep-et sed, awk, perl stb. (a súly növekedésének sorrendjében felsorolva). Az awk használatával a parancs a következőképpen néz ki:
awk "/regexp1/ && /regexp2/ && /regexp3/ { print; }"
, és felépíthető a parancssorban történő egyszerű megadásra.
Megjegyzések
- Ne feledje, hogy
awk
ERE ‘ seket használ, pl. agrep -E
megfelelője, szemben a BRE ‘ -ekkel, amelyeket a simagrep
használ. -
awk
‘ regexeket nevezzük ERE-knek, de valójában ‘ kissé sajátos. Itt valószínűleg további részletek találhatók, mint bárki érdekli: wiki.alpinelinux.org/wiki/Regex - Köszönöm, grep 2.7.3 ( openSUSE). Megszavaztalak, de egy ideig nyitva tartom a kérdést, talán van valami trükk a grep számára (nem mintha nem szeretem a
awk
-t – jobb, ha egyszerűen többet tudok). > - Az alapértelmezett művelet az egyező sor kinyomtatása, így a
{ print; }
rész nem ‘ itt nem igazán szükséges vagy hasznos.
Válasz
Ha az patterns
soronként egy mintát tartalmaz, ilyesmit tehet:
awk "NR==FNR{a[$0];next}{for(i in a)if($0!~i)next}1" patterns -
Vagy ez illeszti az alsorokat a szokásos helyett kifejezések:
awk "NR==FNR{a[$0];next}{for(i in a)if(!index($0,i))next}1" patterns -
Mindegyik nyomtatása a bemenet sorainak helyett ha patterns
üres, cserélje le az NR==FNR
szöveget FILENAME==ARGV[1]
vagy ARGIND==1
itt: gawk
.
Ezek a függvények kinyomtatják az STDIN sorait, amelyek minden argumentumként megadott sztringet tartalmaznak részstringként. A ga
a grep all kifejezést jelenti, a gai
figyelmen kívül hagyja a kis- és nagybetűket.
ga(){ awk "FILENAME==ARGV[1]{a[$0];next}{for(i in a)if(!index($0,i))next}1" <(printf %s\\n "$@") -; } gai(){ awk "FILENAME==ARGV[1]{a[tolower($0)];next}{for(i in a)if(!index(tolower($0),i))next}1" <(printf %s\\n "$@") -; }
Megjegyzések
- éles válasz, amely több felhasználási esetre vonatkozik, és működik (makókon ellenőrizve)
Válasz
grep pattern1 | grep pattern2 | ...
Szeretnék egyetlen grep-et használni, mert dinamikusan építem az argumentumokat, ezért mindennek egy karaktersorozatba kell illeszkednie
Valójában lehetséges dinamikusan megépíteni a csővezetéket (a eval
igénybevétele nélkül):
# Executes: grep "$1" | grep "$2" | grep "$3" | ... function chained-grep { local pattern="$1" if [[ -z "$pattern" ]]; then cat return fi shift grep -- "$pattern" | chained-grep "$@" } cat something | chained-grep all patterns must match order but matter dont
Valószínűleg nem túl hatékony megoldás.
Megjegyzések
- Használja a
chained-grep()
vagy afunction chained-grep
elemet, de ne használja afunction chained-grep()
: unix.stackexchange.com/questions/73750/… - Leírnád, mi a trükk? Hozzáadhatja a válaszhoz ( ” Szerkesztés: “, ” Frissítés: ” vagy hasonló) szerkesztésével ?
- Átfogalmazta a választ, hogy a trükk világosabbá váljon (azaz: dinamikusan építsen héjvezetéket). válasz “>
git grep
Itt található a
git grep
több minta kombinálása logikai kifejezések használatával:git grep --no-index -e pattern1 --and -e pattern2 --and -e pattern3
A fenti parancs egyszerre nyomtatja az összes mintának megfelelő sorokat.
--no-index
Fájlok keresése az aktuális könyvtárban, amelyet a Git nem kezel.Ellenőrizze a
man git-grep
segítségért.Lásd még:
- Hogyan hozzánk e grep, hogy megfeleljen a string1 ÉS string2-nek?
- Ellenőrizze, hogy egy fájlban található-e az összes karakterlánc vagy regexex .
A VAGY művelethez lásd:
- Hogyan lehet többre grepelni minták pipa karakterű mintával?
- Grep: Hogyan adhatunk egy ” VAGY ” feltétel?
Megjegyzések
- Kiváló válasz. Köszönöm.
Válasz
Itt van a véleményem, és ez több soros szavaknál is működik:
Használja a find . -type f
elemet, amelyet annyi
-exec grep -q "first_word" {} \;
és az utolsó kulcsszót a -exec grep -l "nth_word" {} \;
-q
csendes / néma
-l
fájlok megjelenítése egyezésekkel
A következő fájlnevek listáját adja vissza, a “nyúl” és a “lyuk” szavakkal:
find . -type f -exec grep -q "rabbit" {} \; -exec grep -l "hole" {} \;
Megjegyzések
- Ha alaposan megnézed, csak megtudhatod, hogy nem ez a funkció kéri a kérdést.
Válasz
ripgrep
Íme a példa: rg
:
rg -N "(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)" file.txt
Ez az egyik leggyorsabb markoló eszköz, mivel a Rust regex motorja , amely véges automatákat, SIMD-t és agresszív szó szerinti optimalizálásokat használ a keresés nagyon gyors eléréséhez.
Lásd még a kapcsolódó funkciókérést a GH-875 .
Válasz
A összes szó (vagy minta) megkereséséhez futtathatja a grep
parancsot egy for
ciklusban. A fő előny itt a reguláris kifejezések listájáról való keresés .
Valódi példa:
# File "search_all_regex_and_error_if_missing.sh" find_list="\ ^a+$ \ ^b+$ \ ^h+$ \ ^d+$ \ " for item in $find_list; do if grep -E "$item" file_to_search_within.txt then echo "$item found in file." else echo "Error: $item not found in file. Exiting!" exit 1 fi done
Most futtassuk ezt a fájlt:
hhhhhhhhhh aaaaaaa bbbbbbbbb ababbabaabbaaa ccccccc dsfsdf bbbb cccdd aa caa
$ ./search_all_regex_and_error_if_missing.sh aaaaaaa aa ^a+$ found in file. bbbbbbbbb bbbb ^b+$ found in file. hhhhhhhhhh ^h+$ found in file. Error: ^d+$ not found in file. Exiting!
megjegyzések
- Logikája hibás – kértem a
ALL
operátor, a kódOR
operátorként működik, nem pedigAND
. És ehhez btw. (OR
) sokkal könnyebb megoldás, amelyet közvetlenül a kérdésben adunk meg. - @greenoldman A logika egyszerű: A for az összes szóra / mintára hurok a listában, és ha fájlban található – kinyomtatja. Tehát egyszerűen távolítsa el a mást, ha nem szükséges ‘ művelet arra az esetre, ha a szó nem található.
- Értem a logikádat, valamint a kérdésemet – a
AND
operátorról kérdeztem, vagyis a fájl csak akkor pozitív találat, ha egyezik az A mintával és a mintával B és C mintázat, valamint …AND
Ebben az esetben a fájl pozitív találatot ér el, ha ma tches A vagy B mintát, vagy … Látja a különbséget most? - @greenoldman nem biztos benne, miért gondolja, hogy ez a hurok nem ellenőrzi és nem feltételezi az összes mintát? Tehát ‘ valódi példával szerkesztettem a válaszomat: A fájlban a lista összes regexét megkeresi, az első hiányzóban pedig hibával lép ki.
- Közvetlenül a szemed előtt van, pozitív meccsed van közvetlenül az első mérkőzés végrehajtása után. Meg kell, hogy ” gyűjtsön ” az összes kimenetet, és kiszámolja rajtuk a
AND
-t. Ezután át kell írnia a szkriptet, hogy több fájlon fusson – akkor talán rájön, hogy a kérdés már megválaszolt, és a kísérlete nem hoz semmit az asztalra, sajnálom.
foo
-et tartalmaznak, és azokat a sorokat, amelyekbar
” lásd a grep használatával több keresési mintához