Itt van a parancsom (szándékos törés):

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

magasan -szint: grep a FOO-hoz a blah könyvtárban; cső csak a fájlnévben (a -l) – sed; sed soros cserét hajt végre (-i "") és kinyomtatja csak a megváltozott kifejezés /dev/stdout.

Ha kihagynám a -l és pipa, ezt visszakapom a grep címről:

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

Amit szeretnék, az sed a soron belüli csere elvégzéséhez, majd a fájl és a kifejezés helyettesítésének megjelenítéséhez; például:

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

Lehetséges ilyen? Ha ez számít, akkor inkább csak grep / sed értéket tartanám meg. Kell-e egy második grep a ?

Megjegyzések

  • Nem látom a módját annak, hogy <

szerezze be az aktuális fájlnevet sed-ben, így valószínűleg szüksége lesz egy második grep-re.

  • Emellett nem kell ' is szüksége az , ez ' az alapértelmezett.
  • OS X rendszeren a '' nem az alapértelmezett .
  • Válasz

    Az egyik lehetőség a grep külön sed szűrőhöz.

     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/"  

    A sed parancsot kinyomtathatja (a = paranccsal), ha talál egyezést, és tovább utófeldolgozás.

    Valószínűleg egyértelműbb lenne az awk használata.

     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  

    Válasz

    Ahogy én “mn Angol anyanyelvűnek valószínűleg nem értem.

    A könyvtár “grepeléséhez” szüksége van “-r” -re. A “-l” csak a fájlnév használatával nyomtatja ki, és az első előfordulás után abbahagyja a greppelést.

    # 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 

    Válasz

    Azt hiszem, túl bonyolulttá teszi a problémát azzal, hogy megpróbálja egyszerre megtenni. Egyszerűen

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

    szerezd be a fájlok listáját sorszámokkal és helyettesítésekkel (ennek működnie kell, amennyiben a fájlneved nem tartalmaz kettőspontot, de ez amúgy is rossz ötlet a Mac OS-ben …). Ezután kiadhat egy

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

    Itt nincs szükség grepre és xarg-ra (akkor is végezhet “find … | xarg” -ot, ha sok fájlja van). Ha aggódsz a duplikációkról a két sort beírhatja egy szkriptbe vagy függvénybe, és ott változtatható helyettesítéseket végezhet.

    Megjegyzések

    • sed -i ... akkor is megváltoztatja a fájlok idejét, ha a stream változatlan.
    • @jww: igaza van ', hogy ' s, mert egy adatfolyam-szerkesztő, nem fájlszerkesztő, ezért a -i opció sérti az unix filozófiáját ( mywiki.wooledge .org / BashFAQ / 021 # A szabványos_eszközök használata ). Ha ezt el akarja kerülni, használja a következőt: ex (pl. ex -sc '%s/FOO/BAR/ge|x' /Users/gjtorikian/blah).

    Válasz

    Rekurzív módon cserélje le a FOO-t BAR-ra az aktuális dir (csendes mód)

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

    Válasz

    Egy vonalhajó

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

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük