Przetestuj rekurencyjne wyszukiwanie sed i zamień przed uruchomieniem

13

Czy jest jakiś sposób na uruchomienie próbnego wyszukiwania rekurencyjnego i zastąpienie go sedprzed faktycznym uruchomieniem? Chcę tylko wydrukować wyniki przed rozpoczęciem wyszukiwania i zamiany. Coś jak echo wyników,

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
użytkownik251482
źródło
Wykonaj kopię danych, uruchom polecenie, sprawdź wynik.
Kusalananda

Odpowiedzi:

10

Możesz uruchomić sedbez -ii krok po kroku z wyjściemless

grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less

Następnie uruchom za sedpomocą, -i.bakaby utworzyć kopie zapasowe, które możesz później różnicować

grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct

Edycja: Jak sugerowano w komentarzu, użyj grep --null | xargs -0. Powoduje to, że nazwy plików są kończone przez bajt zerowy, co czyni je bezpiecznymi dla nazw plików o nietypowych znakach, takich jak znak nowej linii. Tak, \njest poprawnym znakiem w nazwie pliku unix. Jedynymi zabronionymi postaciami są ukośnik /i znak nul\0

grebneke
źródło
Co ciekawe, próbowałem znaleźć znaczenie -i, ale nie wymieniono go pod man sed. Twoje rozwiązanie zadziałało. Jaki byłby twoim zdaniem najlepszy sposób, aby po prostu wyświetlić listę wierszy, a nie cały plik? Zamiast potokowania na mniej, potokowałem grep term2, który działał, ale otrzymałem również wyniki z dziwnymi znakami.
user251482,
@ user251482 - „Po prostu wypisz linie”, jak w „oglądaniu różnicy między starym a nowym plikiem”?
grebneke
1
@StephaneChazelas Tak, a nawet lepiej, grep -rl --nullponieważ OP nie określił systemu operacyjnego i -Zoznacza coś innego w BSD / OSX (dekompresja). --nulljest taki sam na GNU i BSD
grebneke
1
@grebneke. Dobra uwaga, ale zauważ, że OP używa składni GNU sed, więc możemy założyć, że nie ma BSD. Zauważ, że grepjest to (rozwidlenie) grep GNU na FreeBSD i NetBSD. Na NetBSD -Znadal oznacza --null(według strony podręcznika), ale zgadzam się - null jest bardziej przenośny. Zauważ też, że ani --null ani -Z nie działają na OpenBSD
Stéphane Chazelas
1
@grebneke, jest sed -i '' -e s/.../w BSD sed(nie ma opcjonalnych opcji)
Stéphane Chazelas
5

Użyj sedz findzamiastgrep

Przede wszystkim wolałbym findzamiast tego grep, a to z trzech dobrych powodów:

  1. findpozwala na bardziej precyzyjny wybór pliku. Na przykład grep -r string *.txtda pliki tylko w bieżącym katalogu; nie te w podkatalogach.
  2. findpochodzi z potężną -execopcją, która eliminuje potrzebę całego --null … |xargs 0konstruktu.
  3. Te -readablei -writableopcje finduniemożliwi tracić czasu na plikach, które nie mogą być udostępniane.

Test przechwytywania

To powiedziawszy, grepnadaje się na pierwszy test, aby zobaczyć, co zostanie uchwycone:

$ find . -exec grep term1 {} \;

lub dokładniej:

$ find . -type f -name '*.txt' -readable -writable -exec grep term1 {} \;

Próba

Teraz przejdź do sedpróbnego rozruchu. sedOpcja -njest synonimem --quiet, a pna samym końcu sedwyrazu będzie wydrukować bieżącą przestrzeń wzoru.

$ find . -exec sed -n 's/term1/term2/gp' {} \;

lub dokładniej:

$ find . -type f -name '*.txt' -readable -writable -exec sed -n 's/term1/term2/gp' {} \;

Wykonanie

Jeśli wszystko wygląda dobrze, wydaj ostateczne polecenie, zastępując sedopcję -nprzez -i„na miejscu” i usuwając pna końcu.

$ find . -exec sed -i 's/term1/term2/g' {} \;

lub dokładniej:

$ find . -type f -name '*.txt' -readable -writable -exec sed -i 's/term1/term2/g' {} \;

Więcej findprzykładów

Więcej findprzykładów można znaleźć tutaj .

Serge Stroobandt
źródło