Aș dori să obțin potrivirea multi model cu implicit ȘI între modele, adică echivalent cu executarea mai multor greps într-o secvență:

grep pattern1 | grep pattern2 | ... 

Deci, cum să-l convertiți în ceva de genul?

grep pattern1 & pattern2 & pattern3 

Aș dori să folosesc un singur grep pentru că construiesc argumente dinamic, deci totul trebuie să se potrivească într-un singur șir. Utilizarea filtrului este o caracteristică a sistemului, nu grep, deci nu este un argument pentru asta.


Nu confundați această întrebare cu:

grep "pattern1\|pattern2\|..." 

Acesta este un SAU potrivire cu mai multe tipare.

Comentarii

Răspuns

agrep o poate face cu această sintaxă:

agrep "pattern1;pattern2" 

Cu GNU grep, când este construit w cu suport PCRE, puteți face:

grep -P "^(?=.*pattern1)(?=.*pattern2)" 

Cu ast grep :

grep -X ".*pattern1.*&.*pattern2.*" 

(adăugând .* s ca <x>&<y> se potrivește cu șiruri care se potrivesc atât cu <x>, cât și cu <y> exact , nu s-ar potrivi niciodată, deoarece nu există un astfel de șir care să poată fi atât a, cât și b în același timp).

Dacă modelele nu se suprapun, s-ar putea să faceți și:

grep -e "pattern1.*pattern2" -e "pattern2.*pattern1" 

Cel mai bun mod portabil este probabil cu awk așa cum s-a menționat deja:

awk "/pattern1/ && /pattern2/" 

Cu sed:

sed -e "/pattern1/!d" -e "/pattern2/!d" 

Vă rugăm să aveți grijă ca toți aceștia să aibă sintaxă de expresie regulată diferită.

Comentarii

  • Sintaxa agrep nu funcționează pentru eu … în ce versiune a fost introdusă?
  • @Raman 2.04 din 1992 o avea deja. Nu ‘ nu am niciun motiv să cred că nu a fost ‘ acolo de la început. Versiunile mai noi (după 1992) ale agrep pot fi găsite incluse în glimpse / webglimpse . Este posibil să aveți o implementare diferită. Totuși, am avut o greșeală pentru versiunea ast-grep, opțiunea pentru regexps augmentate este -X, nu -A.
  • @St é phaneChazelas Mulțumesc, am agrep 0.8.0 pe Fedora 23. Acest lucru pare să fii un agrep diferit de cel la care faci referință.
  • @Raman, al tău sună ca TRE agrep .
  • @Techiee, sau doar awk '/p1/ && /p2/ {n++}; END {print 0+n}'

Răspuns

Nu ați specificat versiunea grep, acest lucru este important. Unele motoare regexp permit mai multe potriviri grupate după ȘI folosind „& „dar aceasta este o caracteristică nestandardă și neportabilă. Dar, cel puțin GNU grep nu acceptă acest lucru.

OTOH puteți pur și simplu înlocui grep cu sed, awk, perl etc. . (listat în ordinea creșterii în greutate). Cu awk, comanda ar arăta ca

 awk "/regexp1/ && /regexp2/ && /regexp3/ { print; }" 

și poate fi construită pentru a fi specificată în linia de comandă într-un mod ușor.

Comentarii

  • Amintiți-vă doar că awk folosește ERE ‘ s, de ex. echivalentul grep -E, spre deosebire de BRE ‘ s pe care le folosește simplu grep.
  • awk ‘ regexele sunt numite ERE, dar de fapt ele ‘ re un pic idiosincratic. Iată probabil mai multe detalii decât le pasă oricui: wiki.alpinelinux.org/wiki/Regex
  • Mulțumesc, grep 2.7.3 ( openSUSE). Te-am votat în sus, dar voi menține întrebarea deschisă pentru o vreme, poate există un truc pentru grep (nu că nu-mi place awk – pur și simplu știind mai multe este mai bine).
  • Acțiunea implicită este de a imprima linia potrivită, astfel încât partea { print; } să nu fie ‘ cu adevărat necesară sau utilă aici.

Răspuns

Dacă patterns conține un model pe linie, puteți face așa ceva:

 awk "NR==FNR{a[$0];next}{for(i in a)if($0!~i)next}1" patterns -  

Sau acest lucru se potrivește cu șiruri de caractere în loc de obișnuite expressions:

 awk "NR==FNR{a[$0];next}{for(i in a)if(!index($0,i))next}1" patterns -  

Pentru a imprima toate în loc de linii de intrare în în cazul în care patterns este gol, înlocuiți NR==FNR cu FILENAME==ARGV[1] sau cu ARGIND==1 în gawk.

Aceste funcții imprimă liniile STDIN care conțin fiecare șir specificat ca argument ca subșir. ga înseamnă grep all și gai ignoră majuscule.

 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 "$@") -; }  

Comentarii

  • răspuns clar care abordează mai multe cazuri de utilizare și funcționează (verificat pe macos)

Răspuns

grep pattern1 | grep pattern2 | ...

Aș dori să folosesc un singur grep pentru că construiesc argumente dinamic , așa că totul trebuie să se potrivească într-un singur șir

De fapt, este posibil să construiți conducta dinamic (fără a recurge la eval):

 # 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  

Probabil că nu este o soluție foarte eficientă.

Comentarii

  • Folosiți fie chained-grep(), fie function chained-grep, dar nu function chained-grep(): unix.stackexchange.com/questions/73750/…
  • Puteți descrie care este trucul? Îl puteți adăuga la răspuns ( fără ” Editați: „, ” Actualizare: ” sau similar) prin modificându-l ?
  • Reformularea răspunsului pentru a clarifica trucul (de exemplu: construiți o conductă de shell în mod dinamic)

Răspuns

git grep

Iată sintaxa utilizând git grep combinând mai multe modele folosind expresii Boolean :

git grep --no-index -e pattern1 --and -e pattern2 --and -e pattern3 

Comanda de mai sus va imprima linii care se potrivesc simultan cu toate tiparele.

--no-index Căutați fișiere în directorul curent care nu este gestionat de Git.

Verificați man git-grep pentru ajutor.

Vedeți și:

Pentru operațiunea SAU , consultați:

Comentarii

  • Răspuns superb. Vă mulțumim.

Răspundeți

Aici este ideea mea, iar acest lucru funcționează pentru cuvinte în mai multe rânduri:

Utilizați find . -type f urmat de cât mai multe
-exec grep -q "first_word" {} \;
și ultimul cuvânt cheie cu
-exec grep -l "nth_word" {} \;

-q silent / silent
-l afișează fișiere cu potriviri

Următoarea listă de nume de fișiere cu cuvintele „iepure” și „gaură” în ele:
find . -type f -exec grep -q "rabbit" {} \; -exec grep -l "hole" {} \;

Comentarii

  • Dacă vă uitați cu atenție, s-ar putea să aflați că nu aceasta este funcționalitatea pe care întrebarea o solicită.

Răspuns

ripgrep

Iată exemplul care utilizează rg :

rg -N "(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)" file.txt 

Este unul dintre cele mai rapide instrumente de grepping, deoarece este construit deasupra Motorul regex al lui Rust care folosește automatele finite, SIMD și optimizările literal agresive pentru a face căutarea foarte rapidă.

Consultați și cererea de funcții conexe la GH-875 .

Răspuns

Pentru a găsi toate cuvintele (sau modelele), puteți rula grep într-o buclă for. Principalul avantaj aici este căutarea dintr-o listă de expresii regulate .

Un exemplu real:

# 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 

Acum să-l rulăm pe acest fișier:

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! 

Comentarii

  • Logica dvs. este defectă – am cerut ALL operator, codul dvs. funcționează ca operator OR, nu AND. Și btw. Pentru asta (OR) este o soluție mult mai ușoară dată chiar în întrebare.
  • @greenoldman Logica este simplă: for va bucla pe TOATE cuvintele / tiparele în listă și, dacă este găsit în fișier, îl va imprima. Deci, eliminați celălalt, dacă nu aveți nevoie de ‘ acțiune în cazul în care cuvântul nu a fost găsit.
  • Înțeleg logica dvs., precum și întrebarea mea – întrebam despre operatorul AND, adică fișierul este doar o lovitură pozitivă dacă se potrivește cu modelul A și modelul B și modelul C și … AND În cazul dvs. fișierul este lovit pozitiv dacă este tches modelul A sau modelul B sau … Vedeți diferența acum?
  • @greenoldman nu sunteți sigur de ce credeți că această buclă nu verifică ȘI condiția ȘI pentru toate modelele? Așa că ‘ mi-am editat răspunsul cu un exemplu real: va căuta în fișier toate regexurile listei, iar pe primul care lipsește – va ieși cu eroare.
  • Îl aveți chiar în fața ochilor, aveți un meci pozitiv imediat după ce primul meci este executat. Ar trebui să aveți ” colectați ” toate rezultatele și să calculați AND pe ele. Apoi, ar trebui să rescrieți scriptul pentru a rula pe mai multe fișiere – apoi poate vă dați seama că întrebarea este deja răspunsă și încercarea dvs. nu aduce nimic la masă, scuze.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *