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 unagrep
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. echivalentulgrep -E
, spre deosebire de BRE ‘ s pe care le folosește simplugrep
. -
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()
, fiefunction chained-grep
, dar nufunction 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:
- Cum să ne e grep pentru a se potrivi cu șirul1 ȘI șirul2?
- Verificați dacă există mai multe șiruri sau regexe într-un fișier .
Pentru operațiunea SAU , consultați:
- Cum grep pentru multiple șabloane cu un șablon având un caracter pipă?
- Grep: cum se adaugă un ” SAU ” condiție?
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 operatorOR
, nuAND
. Ș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.
foo
și linii care conținbar
” vezi folosind grep pentru mai multe modele de căutare