Tady je můj příkaz (úmyslné přerušení):

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

Na nejvyšší úrovni -level: grep pro FOO v adresáři blah; potrubí pouze v názvu souboru (z důvodu -l) to sed; sed provede vloženou výměnu (-i "") a vytiskne pouze změněný výraz na /dev/stdout.

Pokud bych vynechal -l a potrubí, dostanu to zpět z grep:

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

Chci však sed provést vložené nahrazení a poté mi ukázat nahrazený soubor a výraz; například:

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

Je něco takového možné? Pokud na tom záleží, raději bych to nechal pouze s grep / sed. Musím udělat druhý grep po ?

Komentáře

  • Nevidím ' způsob, jak získejte aktuální název souboru v sed, takže pravděpodobně budete potřebovat druhý grep.
  • Také nepotřebujete ' '', že ' je výchozí.
  • V OS X není '' výchozí .

Odpověď

Jednou z možností by bylo předat výstup grep do samostatného sed filtru.

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

Když zjistíte shodu, můžete sed vytisknout číslo řádku (pomocí příkazu =) a provést další postprocesing.

Pravděpodobně by bylo jasnější použít 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  

Odpověď

Jak jsem „mn ot rodilý mluvčí angličtiny Pravděpodobně jsem to nedostal.

Chcete-li „grepovat“ adresář, potřebujete „-r“. Použití „-l“ vytiskne pouze název souboru a přestane grepovat po prvním výskytu.

# 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 

Odpovědět

Myslím, že problém příliš komplikujete tím, že se ho snažíte zvládnout najednou. Můžete jednoduše udělat

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

získejte seznam souborů s čísly řádků a náhradami (mělo by to fungovat, pokud vaše názvy souborů neobsahují dvojtečky, ale to je v Mac OS stejně špatný nápad …). Poté můžete vydat

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

Zde není potřeba žádný grep a xarg (pokud však máte spoustu souborů, můžete provést „find … | xarg“. Pokud máte obavy o duplikacích můžete tyto dva řádky vložit do skriptu nebo funkce a provést tam proměnné náhrady.

Komentáře

  • sed -i ... mění časy souborů, i když se stream nezmění.
  • @jww: máte ' pravdu, že ' s protože je editor streamů, nikoli editor souborů, takže možnost -i porušuje unixovou filozofii ( mywiki.wooledge .org / BashFAQ / 021 # Using_nonstandard_tools ). Pokud se tomu chcete vyhnout, použijte ex (např. ex -sc '%s/FOO/BAR/ge|x' /Users/gjtorikian/blah).

Odpovědět

Rekurzivně nahradit FOO za BAR v aktuálním adresáři (tichý režim)

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

Odpověď

Jedna linka

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

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *