Haluaisin saada monen mallin vastaavan implisiittistä JA kuvioiden välillä, eli vastaa useita greppejä sarjassa:

grep pattern1 | grep pattern2 | ... 

Joten miten se voidaan muuntaa sellaiseksi?

grep pattern1 & pattern2 & pattern3 

Haluaisin käyttää yksittäistä grep-tiedostoa, koska rakennan argumentteja dynaamisesti, joten kaiken on mahtuttava yhteen merkkijonoon. Suodattimen käyttö on järjestelmäominaisuus, ei grep, joten se ei ole argumentti sille.


Älä sekoita tätä kysymystä seuraavaan:

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

Tämä on TAI monikuvio.

Kommentit

vastaus

agrep voi tehdä sen tällä syntaksilla:

agrep "pattern1;pattern2" 

GNU: lla grep, kun se on rakennettu w PCRE-tuella voit tehdä seuraavaa:

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

ast grep :

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

(lisäämällä .* s nimellä <x>&<y> vastaa merkkijonoja, jotka vastaavat sekä <x> että <y> tarkalleen , a&b ei koskaan täsmää, koska ei ole sellaista merkkijonoa, joka voi olla sekä a että b samaan aikaan).

Jos mallit eivät ole päällekkäisiä, voit ehkä tehdä myös seuraavat toiminnot:

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

Paras kannettava tapa on todennäköisesti awk, kuten jo mainittiin:

awk "/pattern1/ && /pattern2/" 

Kanssa sed:

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

Ole varovainen, että kaikilla niillä on erilainen säännöllisen lausekkeen syntaksit.

Kommentit

  • agrep -syntaksi ei toimi minä … missä versiossa se otettiin käyttöön?
  • @Raman 2.04 vuodelta 1992 oli jo ollut siinä. Minulla ’ ole mitään syytä uskoa, ettei sitä ollut alusta alkaen ’. Uudemmat (vuoden 1992 jälkeen) versiot agrep: stä löytyvät glimpse / webglimpse -sisältöstä. Mahdollisesti sinulla on erilainen toteutus. Minulla oli kuitenkin virhe ast-grep-versiossa, vaihtoehto lisätyille regexpsille on -X, ei -A.
  • @St é phaneChazelas Kiitos, minulla on agrep 0.8.0 Fedora 23: ssa. Tämä näyttää olla erilainen agrep kuin viittaamasi.
  • @Raman, sinun kuulostaa TRE agrep .
  • @Techiee tai vain awk '/p1/ && /p2/ {n++}; END {print 0+n}'

Vastaus

Et määritä grep-versiota, tämä on tärkeää. Jotkut regexp-moottorit sallivat useiden haun ryhmiteltyinä JA: lla käyttämällä ”& ”mutta tämä ei ole standardi eikä kannettava ominaisuus. Mutta ainakaan GNU grep ei tue tätä.

OTOH voit yksinkertaisesti korvata grep: n sedillä, awk: llä, perlillä jne. (lueteltu painonnousun järjestyksessä). Awk: n kanssa komento näyttäisi tältä:

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

ja se voidaan rakentaa määritettäväksi komentorivillä helposti.

Kommentit

  • Muista vain, että awk käyttää ERE ’ s, esim. vastaa grep -E, toisin kuin BRE ’, joita tavallinen grep käyttää.
  • awk ’ regeksejä kutsutaan EREiksi, mutta itse asiassa ne ’ uudelleen hieman omaperäinen. Tässä on todennäköisesti enemmän yksityiskohtia kuin kukaan välittää: wiki.alpinelinux.org/wiki/Regex
  • Kiitos, grep 2.7.3 ( openSUSE). Äänestin sinua, mutta pidän kysymyksen avoimena jonkin aikaa, ehkä grepillä on jokin temppu (enkä pidä siitä, että en pidä awk – en yksinkertaisesti tiedä enemmän on parempi).
  • Oletustoiminto on tulostaa vastaava viiva, joten { print; } -osa ei ole ’ t todella tarpeellinen tai hyödyllinen tässä.

vastaus

Jos patterns sisältää yhden kuvion riviä kohden, voit tehdä jotain tältä:

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

Tai tämä sopii alijonkoihin tavallisen sijaan lausekkeet:

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

Tulostaa kaikki sen sijaan, että syötteessä olisi rivejä Jos patterns on tyhjä, korvaa NR==FNR tilalla FILENAME==ARGV[1] tai ARGIND==1 ryhmässä gawk.

Nämä toiminnot tulostavat STDIN: n rivit, jotka sisältävät kukin argumenttina määritetyn merkkijonon alimerkkinä. ga tarkoittaa grep all ja gai ei huomioi kirjainkokoa.

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

kommentit

  • terävä vastaus, joka käsittelee useita käyttötapauksia ja toimii (vahvistettu macoilla)

vastaus

grep pattern1 | grep pattern2 | ...

Haluaisin käyttää yksittäistä grep-tiedostoa, koska rakennan argumentteja dynaamisesti , joten kaiken on mahtuttava yhteen merkkijonoon

Putkilinjan rakentaminen on todella mahdollista dynaamisesti (turvautumatta 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  

Se ei kuitenkaan todennäköisesti ole kovin tehokas ratkaisu.

Kommentit

  • Käytä joko chained-grep() tai function chained-grep, mutta älä function chained-grep(): unix.stackexchange.com/questions/73750/…
  • Voitteko kuvata temppua? Voitko lisätä sen vastaukseen ( ilman ” Muokkaa: ”, ” Päivitä: ” tai vastaava) muokkaamalla sitä ?
  • muotoili vastauksen uudelleen, jotta temppu olisi selkeämpi (ts. rakenna kuoren putki dynaamisesti)

vastaus

git grep

Tässä on syntaksia käyttäen git grep yhdistämällä useita kuvioita Boolean lausekkeilla:

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

Yllä oleva komento tulostaa rivit, jotka vastaavat kaikkia malleja kerralla.

--no-index Hae tiedostoja nykyisestä hakemistosta, jota Git ei hallinnoi.

Tarkista man git-grep saadaksesi apua.

Katso myös:

Katso TAI -toimintoa kohdasta:

Kommentit

  • Erinomainen vastaus. Kiitos.

Vastaa

Tässä on mielipiteeni, ja tämä toimii monirivisillä sanoilla:

Käytä find . -type f, jota seuraa mahdollisimman monta
-exec grep -q "first_word" {} \;
ja viimeistä avainsanaa merkillä
-exec grep -l "nth_word" {} \;

-q hiljainen / hiljainen
-l näytä tiedostot osumilla

Seuraava palauttaa luettelon tiedostojen nimistä, joissa on sanat ”kani” ja ”reikä”:
find . -type f -exec grep -q "rabbit" {} \; -exec grep -l "hole" {} \;

Kommentit

  • Jos katsot tarkkaan, saatat vain tietää, että tätä ei kysytä toiminnalta.

vastaus

ripgrep

Tässä on esimerkki rg :

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

Se on yksi nopeimmista tartuntatyökaluista, koska se on rakennettu Rustin regex-moottori , joka käyttää äärellisiä automaatteja, SIMD: tä ja aggressiivisia kirjaimellisia optimointeja, jotta haku olisi nopeaa.

Katso myös aiheeseen liittyvä ominaisuuspyyntö osoitteessa GH-875 .

Vastaa

Löydät kaikki sanat (tai kuviot) suorittamalla grep -silmukan for -silmukassa. Tärkein etu on tässä haku säännöllisten lausekkeiden luettelosta .

Todellinen esimerkki:

# 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 

Suorita se nyt tässä tiedostossa:

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! 

kommentit

  • Logiikkasi on virheellinen – pyysin ALL -operaattori, koodisi toimii OR -operaattorina, ei AND. Ja btw. (OR) on paljon helpompi ratkaisu, joka annetaan heti kysymyksessä.
  • @greenoldman Logiikka on yksinkertainen: for silmukkaa kaikki sanat / kuviot luettelossa, ja jos se löytyy tiedostosta – tulostaa sen. Poista siis muu, jos et ’ tarvitse toimia, jos sanaa ei löydy.
  • Ymmärrän sekä logiikkasi että kysymykseni – kysyin AND -operaattorista, eli tiedosto on positiivinen osuma vain, jos se vastaa mallia A ja mallia B ja kuvio C ja … AND Jos tiedosto on positiivinen osuma, jos se tches kuvio A tai kuvio B tai … Näetkö eron nyt?
  • @greenoldman ole varma, miksi luulet, että tämä silmukka ei tarkista JA ehtoja kaikille kuvioille? Joten olen ’ muokannut vastaustani todellisella esimerkillä: Se etsii tiedostosta kaikkia luettelon lausekkeita, ja ensimmäisestä puuttuvasta – poistuu virheellisesti.
  • Sinulla on se silmiesi edessä, sinulla on positiivinen ottelu heti ensimmäisen ottelun suorittamisen jälkeen. Sinun tulisi ” kerätä ” kaikki tulokset ja laskea niistä AND. Sitten sinun pitäisi kirjoittaa komentosarja uudelleen, jotta se toimii useilla tiedostoilla – sitten ehkä huomaat, että kysymykseen on jo vastattu, eikä yrityksesi tuo mitään pöydälle, anteeksi.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *