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 erilainenagrep
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. vastaagrep -E
, toisin kuin BRE ’, joita tavallinengrep
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()
taifunction 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:
- Ohjeet meille e grep vastaamaan merkkijonoa1 JA merkkijonoa2?
- Tarkista, onko tiedostossa kaikkia useita merkkijonoja tai regeksejä .
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 toimiiOR
-operaattorina, eiAND
. 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.
foo
ja rivejä, jotka sisältävätbar
” katso grepin käyttämistä useille hakumalleille