Tässä on komentoni (rikkoa tahallista):

grep FOO "/Users/gjtorikian/blah" -l | xargs sed -i "" "/FOO/{s/FOO/BAR/g; w /dev/stdout }" 

Ylhäällä -taso: grep FOO: lle hakemistossa blah; putki vain tiedostonimessä (-l) – sed; sed suorittaa rivinvaihdon (-i "") ja tulostaa vain muutettu termi muotoon /dev/stdout.

Jos jätän pois -l ja putki, saan tämän takaisin grep:

/Users/gjtorikian/blah/baz.cs:1:FOO /Users/gjtorikian/blah/bar.js:1:FOO 

Haluan sed suoran korvaamisen suorittamiseksi ja sitten minulle korvatun tiedoston ja termin näyttämiseksi; esimerkiksi:

/Users/gjtorikian/blah/baz.cs:1:BAR /Users/gjtorikian/blah/bar.js:1:BAR 

Onko sellainen mahdollista? Jos sillä on merkitystä, haluaisin mieluummin säilyttää sen vain grep / sed kanssa. Pitääkö minun tehdä toinen grep ?

Kommentit

  • En näe ' en näe tapaa hae nykyinen tiedostonimi sed-muodossa, joten tarvitset todennäköisesti toisen grepin.
  • Et myöskään tarvitse ' et '', että ' on oletus.
  • OS X: ssä '' ei ole oletusarvo. .

vastaus

Yksi mahdollisuus olisi välittää grep erilliseen sed suodattimeen.

 grep -l FOO "/Users/gjtorikian/blah/"* | { tee /dev/fd/3 | xargs sed -i -e "/FOO/{" -e "s/FOO/BAR/g" -e "w /dev/stdout" } 3>&1 | sed "s/:FOO$/:BAR/"  

Voit tehdä sed tulostamaan rivinumeron (komennolla =), kun se löytää osuman, ja tehdä edelleen jälkikäsittely.

On todennäköisesti selvempää käyttää awk.

 for x in "/Users/gjtorikian/blah/"*; do awk " sub(/FOO/, "BAR") {found=1; print FILENAME ":" NR ":" "BAR" >"/dev/stderr"} 1 {print} END {exit(!found)} " "$x" >"$x.tmp" && mv "$x.tmp" "$x" done  

Vastaa

Kuten minä ”mn Englannin äidinkielenään puhuvalle henkilölle en luultavasti saanut sitä.

Hakemiston ”nappaamiseen” tarvitset ”-r”. ”-L” -tulosten käyttö vain tiedostonimellä ja se lopettaa rypistyksen ensimmäisen esiintymisen jälkeen.

# pattern=/home ; grep -l "$pattern" /etc/[a-z]* 2>/dev/null | while read line ; do echo "$line:$pattern" ; done /etc/adduser.conf:/home /etc/fstab:/home /etc/fstab~:/home /etc/libuser.conf:/home /etc/mpd.conf:/home /etc/mpd.conf~:/home /etc/mtab:/home /etc/netscsid.conf:/home /etc/passwd:/home /etc/passwd-:/home /etc/sudoers:/home /etc/sudoers.tmp~:/home 

Vastaa

Luulen, että teet ongelman liian monimutkaiseksi yrittämällä tehdä sen yhdellä kertaa. Voit yksinkertaisesti tehdä

grep -H -n /Users/gjtorikian/blah | sed "s/\(^.*?:[0-9]+?:\).*FOO.*/\1BAZ/" 

hae luettelo tiedostoista, joissa on rivinumerot ja korvaukset (tämän pitäisi toimia, kunhan tiedostonimet eivät sisällä kaksoispisteitä, mutta se on silti huono idea Mac OS: ssä …). Sen jälkeen voit antaa

sed -i "" "s/FOO/BAR/g" /Users/gjtorikian/blah 

Täällä ei tarvita grepiä ja xargia (voit tehdä ”etsi … | xarg”, jos sinulla on kuitenkin paljon tiedostoja). Jos olet huolissasi kaksoiskappaleista, voit laittaa kaksi riviä komentosarjaan tai funktioon ja tehdä siellä vaihtuvia korvauksia.

Kommentit

  • sed -i ... muuttaa tiedostoja, vaikka virta ei muutu.
  • @jww: olet ' oikeassa, että ' s koska on virtaeditori, ei tiedostojen muokkausohjelma, joten vaihtoehto -i rikkoo unix-filosofiaa ( mywiki.wooledge .org / BashFAQ / 021 # Using_nonstandard_tools ). Jos haluat välttää sitä, käytä ex (esim. ex -sc '%s/FOO/BAR/ge|x' /Users/gjtorikian/blah).

Vastaa

Korvaa FOO rekursiivisesti BAR: lla nykyisessä dir-tilassa (hiljainen tila)

grep -rl "FOO" | xargs sed -i "s/FOO/BAR/" 

Vastaa

Yksi linja

grep -n FOO * -R|awk -F\: "{ print $1 }"|sort|uniq|while read file; do sed -i "s/FOO/BAR/g" $file; done 

Vastaa

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