Tähän kysymykseen on jo annettu vastauksia :

Kommentit

  • Mitä tarkoitat kirjoittanut " jokaisen merkkijonon koko osan "? Et ' et halua, että koko rivi tulostetaan?
  • Voisitko vahvistaa, että haluat, että vastaavat tiedostot sisältävät molemmat " foo " ja " 321 " mutta ei vain " foo " tai vain " 321 "?
  • Pidän siitä, miten se ' s 321 bar -kohdan sijaan: – D

Vastaa

GNU grep

Pitäisi olla hieman nopeampi, koska toinen grep voi toimia tiedostoluettelossa.

grep -lZ "foo" * | xargs -0 grep -l "321" 

POSIX-grep ja etsi

find on hyödyllisempi, jos haluat etsiä rekursiivisista hakemistoista (tällöin menetät -mindepth ja -maxdepth vaihtoehdot.

find . -mindepth 1 -maxdepth 1 -type f -exec grep -q "foo" {} \; -exec grep -l "321" {} + 

Kommentit

  • -r toimi hyvin ensimmäisellä grep, jotta GNU-ratkaisu olisi rekursiivinen minulle, sen sijaan, että käyttäisit POSIX-riviä kaikkien niiden kanssa exec s

Vastaa

Voit tehdä tämän lyhyellä komentosarjalla:

for FILE in * do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE done 

Voit tehdä tämän myös yhdellä rivillä:

for FILE in *; do grep -q foo $FILE && grep -q 321 $FILE && echo $FILE; done 

grep palauttaa arvon 0 (true), jos se löysi merkkijonon ja komennot erottava && tarkoittaa, että toinen toimii vain, jos ensimmäinen oli totta. -q -vaihtoehto varmistaa, että grep ei tuota mitään.

Kaiku toimii vain, jos molemmat merkkijonot olivat löytyy samasta tiedostosta.


Ajattelin eri tapaa tehdä se. Tämä tapa on todennäköisesti tehokkaampi, jos kyseiset tiedostot ovat suurempia kuin asennettu RAM-muistisi, koska sen täytyy vain grep käydä läpi jokainen tiedosto kerran.

 for FILE in * do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE done 

ja yksirivinen versio:

 for FILE in *; do test $(egrep -o "foo|321" $FILE | uniq | sort | uniq | wc -l) -eq 2 && echo $FILE; done 

kommentit

  • Tehokkaampaa ratkaisua varten: entä jos tiedostossa on " foo foo "?
  • Että ' s mitä uniq | sort | uniq on tarkoitettu. " foo foo " on lopulta yksi rivi, mutta " foo 321 " on loppujen lopuksi kaksi riviä, koska grep -o tuottaa kaikki löydetyt merkkijonot erillisillä riveillä, vaikka ne aloittaisivat samalla rivillä.
  • Jos tiedostoista tulee niin suuria, että haarautuminen vähintään kuusi kertaa tiedostoa kohden on OK, on luultavasti järkevää käyttää sen sijaan awk-tiedostoa, jotta tiedostoja ei tarvitse etsiä loppuun asti.
  • @Ladadadada sai se. 🙂
  • @HaukeLaging grep -q ja grep -l ei etsi tiedoston loppuun: ne poistuvat heti koska ottelu löytyy. Se saa minut miettimään, miksi ensimmäinen ratkaisu ei ole ' t for FILE in *; do grep -q foo "$FILE" && grep -l 321 "$FILE"; done

vastaus

Outoa. Minulle molemmat vaihtoehdot toimivat (grep (GNU grep) 2.13):

grep "foo\|321" grep -E "foo|321" 

Muokkaa 1 – näytä vain molempien vastaavuuksien tiedostot

for file in * -vastaus toimii, mutta siitä voi tulla suorituskykyinen painajainen (suurille tiedostoille ): vähintään kaksi prosessia tiedostoa kohden. Tämä on nopeampaa (GNU-maailmassa):

find . -type f -print0 | xargs -0 -r grep --files-with-matches --null -- string1 | xargs -0 -r grep --files-with-matches -- string2 

Merkkijonon 1 pitäisi olla se, joka johtaa vähemmän otteluihin.

Kommentit

  • Kysyjä etsii tuloksen palautuvan tosi vain, jos tiedosto sisältää molemmat merkkijonot sen sijaan, että se vain sopisi vähintään yhteen.
  • Pidän siitä --files-with-matches -vaihtoehto. Lukekaa se vain man-sivulta ja se saa grepin lopettamaan ensimmäisen haun löytymisen vuoksi, mikä tarkoittaa, että se ' on erittäin tehokas suurille tiedostoille, jos ottelu tapahtuu aikaisin. Siinä sanotaan myös, että lyhyt vaihtoehto -l on POSIXin määrittelemä, joten sitä voidaan käyttää GNU-maailman ulkopuolella.
  • @Ladadadada Tehokkuus ei ole etu -q kuitenkin. Mainitsemalla GNU: ta en ollut ' ajatellut –file-with-matchs vaan -0 / –null.Mikä vain tulee mieleeni: polunimen laajennus sisältää aakkosellisen lajittelun (todella huono: Näyttää siltä, että se voidaan ' ei edes sammuttaa), joten for file in * ei enää todellakaan ole hauskaa.
  • Tehokkuuden optimointi olisi todellakin erilainen muutamille suurille tiedostoille verrattuna paljon pieniin ja * vain ei ole ' ei toimi lainkaan muutaman tuhannen tiedoston jälkeen.
  • @Ladadadada Se ei ' t toimii osana ulkoisen komennon komentoriviä: grep foo * Mutta for file in * on kuoren sisäinen rakenne, joten oletan että komentorivirajaa ei voida käyttää tässä.

Vastaa

Periaatteessa kaikkien tiedostojen löytäminen tietyn mukaan lukien merkkijono hakemistossa, voit käyttää tätä:

grep -lir "pattern" /path/to/the/dir 
  • -l: tehdäksesi skannauksen pysähtyy ensimmäisellä ottelulla
  • -i: ohitetaan sekä kuvio- että syötetiedostojen kirjainkoon erot
  • -r: etsi kaikki hakemiston tiedostot rekursiivisesti

Jos haluat etsiä kahta mallia, kokeile tätä:

grep -lr "321" $(grep -lr "foo" /path/to/the/dir) 

Kommentit

  • Tavalliset tylsät kommentit siitä, että $() ei käsittele välilyöntejä, ovat voimassa. Käytännössä tämä komento toimii yhdellä linjassa kuoressa.

Vastaus

Pitäisi olla

grep -e "foo" -e "321" * 

Käytä -e useille kuvioille

MUOKKAA

Jos tarvitset molempia:

grep -e ".*foo.*321.*" * 

Jos järjestyksellä ei ole väliä:

grep -e ".*foo.*321.*" ".*321.*foo.*" * 

Kommentit

  • Tämä ei anna vastausta kysymykseen. Jätä kommentti kirjoittajan kritiikkiin tai pyydä selvennystä kirjoittajalta.
  • @mdpc Mielestäni se antaa vastauksen. Mikä saa sinut ajattelemaan erilaista?
  • @HaukeLaging Koska se palaa, jos jompikumpi kuvio sopii. OP etsii tapausta, jossa se palaa tosi vain, jos molemmat löytyy tiedostosta.
  • Ymmärrän, että löydän vain tiedostot, joissa molemmat merkkijonot sisältävät samalla rivillä (I älä ' usko. vastaa oletuksena uusia rivejä)

Vastaa

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