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.
''
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
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
sed -i ...
akkor is megváltoztatja a fájlok idejét, ha a stream változatlan.-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
).