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ás agrep, 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. a grep -E megfelelője, szemben a BRE ‘ -ekkel, amelyeket a sima grep 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

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ód OR operátorként működik, nem pedig AND. É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.

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