Czy masz na myśli wyszukiwanie i zamianę ciągu we wszystkich plikach dopasowanych przez grep?
perl -p -i -e 's/oldstring/newstring/g' `grep -ril searchpattern *`
Edytować
Ponieważ wydaje się to dość popularne pytanie, pomyślałem, że zaktualizuję.
Obecnie najczęściej używam, ack-grep
ponieważ jest bardziej przyjazny dla użytkownika. Więc powyższe polecenie brzmiałoby:
perl -p -i -e 's/old/new/g' `ack -l searchpattern`
Aby obsłużyć białe znaki w nazwach plików, możesz uruchomić:
ack --print0 -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
możesz zrobić więcej ack-grep
. Załóżmy, że chcesz ograniczyć wyszukiwanie tylko do plików HTML:
ack --print0 --html -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
A jeśli biała przestrzeń nie jest problemem, jest jeszcze krótsza:
perl -p -i -e 's/old/new/g' `ack -l --html searchpattern`
perl -p -i -e 's/old/new/g' `ack -f --html`
Can't open Untitled: No such file or directory, <> line 5
podczas próby „Untitled Folder / file.txt”.Wygląda na to, że chcesz, na podstawie podanego przykładu:
sed -i 's/foo/bar/g' *
Nie jest rekursywny (nie schodzi do podkatalogów). Aby uzyskać fajne rozwiązanie zastępując wybrane pliki w całym drzewie, użyłbym find:
find . -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
Jest
*.html
to wyrażenie, które musi pasować do plików, a.bak
po wykonaniu-i
kopii oryginalnego pliku z rozszerzeniem .bak (może to być dowolne rozszerzenie), ag
na końcu wyrażenia sed nakazuje sedowi zamianę wielu kopii jedna linia (a nie tylko pierwsza). Funkcja-print
znajdowania to wygoda pokazania, które pliki zostały dopasowane. Wszystko to zależy od dokładnych wersji tych narzędzi w twoim systemie.źródło
find
komendę katalog, od którego ma zacząć, na przykładfind . -name '*.html'
lubfind directoryname/ -name '*'
.sed -ie 's/foo/bar/g' *
Jeśli urządzenie
sed(1)
posiada-i
opcję, a następnie używać go w ten sposób:for i in *; do sed -i 's/foo/bar/' $i done
Jeśli nie, istnieje kilka sposobów na różne warianty następujących elementów, w zależności od tego, w jakim języku chcesz grać:
ruby -i.bak -pe 'sub(%r{foo}, 'bar')' * perl -pi.bak -e 's/foo/bar/' *
źródło
for i in *; do ...
jest zbędne, sed może przyjąć listę plików jako argumenty.for i in *; do; sed -i 's/foo/bar/g' "$i"; done
Podobało mi się i korzystałem z powyższego rozwiązania lub przeszukiwania całego systemu i zastępowania wśród tysięcy plików:
find -name '*.htm?' -print -exec sed -i.bak 's/foo/bar/g' {} \;
Zakładam z „* .htm?” zamiast .html wyszukuje i znajduje zarówno pliki .htm, jak i .html.
Zastąpiłem .bak bardziej używaną w systemie tyldą (~), aby ułatwić czyszczenie plików kopii zapasowych.
źródło
Działa to przy użyciu grepa bez konieczności używania perla lub find.
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
źródło
-i
że nie działa dla innych systemów operacyjnych. Działa dla mnie na ubuntu.xargs
podręcznika (w systemie Ubuntu) jest napisane, że-i
jest to przestarzałe i do użycia-I
zamiast tego. Tak więc powinniśmy powiedzieć:grep -rli 'old-word' * | xargs -I filepath sed -i 's/old-word/new-word/g' filepath
find . -type f -print0 | xargs -0 <sed/perl/ruby cmd>
będzie przetwarzać nazwy plików w wielu przestrzeniach jednocześnie, ładując po jednym tłumaczu na wsad. O wiele szybciej.źródło
Odpowiedź już udzielona na temat używania funkcji find i sed
find -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
to prawdopodobnie standardowa odpowiedź. Lub możesz użyć
perl -pi -e s/foo/bar/g'
zamiastsed
polecenia.W przypadku większości szybkich zastosowań może się okazać, że polecenie rpl jest łatwiejsze do zapamiętania. Oto zamiana (foo -> bar), rekurencyjnie dla wszystkich plików w bieżącym katalogu:
rpl -R foo bar .
Nie jest domyślnie dostępny w większości dystrybucji Linuksa, ale można go szybko zainstalować (
apt-get install rpl
lub podobnie).Jednak w przypadku trudniejszych zadań, które obejmują wyrażenia regularne i podstawianie z powrotem lub zmianę nazw plików, a także wyszukiwanie i zastępowanie, najbardziej ogólnym i potężnym narzędziem, o którym wiem, jest repren , mały skrypt w Pythonie, który napisałem jakiś czas temu bardziej skomplikowane zadania związane ze zmianą nazw i refaktoryzacją. Powody, dla których możesz to preferować, to:
Przykłady można znaleźć w pliku README .
źródło
W rzeczywistości jest to łatwiejsze niż się wydaje.
grep -Rl 'foo' ./ | xargs -n 1 -I % sh -c "ls %; sed -i 's/foo/bar/g' %";
Bułka z masłem. Jeśli dobrze zrozumiesz find, grep, xargs, sed i awk, prawie nic nie jest niemożliwe, jeśli chodzi o manipulowanie plikami tekstowymi w bash :)
źródło