Chcę wyszukać i zamienić trochę tekstu w dużym zestawie plików, z wyjątkiem niektórych wystąpień. Dla każdej linii chcę monit z pytaniem, czy muszę ją zastąpić, czy nie. Coś podobnego do vima :%s/from/to/gc
(z c
monitem o potwierdzenie), ale w zestawie folderów. Czy jest jakieś dobre narzędzie lub skrypt wiersza poleceń, którego można użyć?
11
s/from/to/g
z usterką formatowania po nim, zamiasts/from/to/gc
z naciskiem na to,c
jak próbowałeś pisać (nie możesz tego zrobić za pomocą Markdown, możesz to zrobić za pomocą<code>
i<strong>
tagi HTML).Odpowiedzi:
Dlaczego nie użyć vima?
Otwórz wszystkie pliki w vimie
Lub otwórz tylko odpowiednie pliki (zgodnie z sugestią Caleb)
A następnie uruchom polecenie replace we wszystkich buforach
Możesz to również zrobić
sed
, ale moja wiedza jest ograniczona.źródło
grep
zamiastfind
, aby otwierać tylko te pliki, które są zgodne.vim $(grep 'from' . -Rl)
Możesz zrobić coś prymitywnego za pomocą małego skryptu Perla, który jest instruowany do wykonywania zamiany wiersz po wierszu (
-l -pe
) na plikach przekazywanych jako argumenty (-i
):Możliwe ulepszenia polegałyby na kolorowaniu części monitu i wsparciu takich rzeczy jak „zamień wszystkie wystąpienia w bieżącym pliku”. Oddzielne monitowanie o każde wystąpienie w linii byłoby trudniejsze.
Druga część, dopasowanie plików. jeśli nie ma zbyt wielu plików i korzystasz z zsh, możesz rekurencyjnie dopasować wszystkie pliki w bieżącym katalogu i jego podkatalogach:
Jeśli twoja powłoka ma bash ≥4, możesz uruchomić
perl … **/*
, ale spowoduje to fałszywe komunikaty o błędach, ponieważ sed spróbuje (i nie powiedzie się) uruchomić w katalogach. Jeśli chcesz wykonać zamianę tylko w zestawie plików, takich jak pliki C, możesz ograniczyć dopasowania (działa to zarówno w bash ≥4, jak i zsh):Jeśli potrzebujesz dokładniejszej kontroli nad zamienianymi plikami lub twoja powłoka nie ma rekurencyjnej struktury dopasowywania katalogu
**
lub jeśli masz zbyt wiele plików i pojawia się błąd „zbyt długiej linii poleceń”, użyjfind
. Na przykład, aby wykonać zamianę we wszystkich nazwanych plikach*.h
lub*.c
w bieżącym katalogu i jego podkatalogach (w starszych systemach może być konieczne użycie\;
zamiast+
na końcu wiersza (+
formularz jest szybszy, ale nie wszędzie dostępny).To powiedziawszy, trzymałbym się interaktywnego edytora, jeśli potrzebujesz interakcji. Gert wskazał na to sposób w Vimie , choć wymaga otwarcia wszystkich plików, które chcesz przeszukać, co może być problemem, jeśli jest ich dużo.
W Emacs możesz to zrobić w następujący sposób:
M-x find-name-dired
(podaj katalog najwyższego poziomu) lubM-x find-dired
(podaj dowolnyfind
wiersz poleceń).t
, aby zaznaczyć wszystkie pliki, a następnieQ
(dired-do-query-replace-regexp
) aby przeprowadzić wymianę z prośbą o zaznaczonych plików.źródło
sdiff
(patrz http://www.gnu.org/software/diffutils/manual/diffutils.html#Invoking-sdiff ) może się tu przydać. Dzięki niemu możesz wykonywać interaktywne łatanie. Tak więcsed
rozwiązaniem może być plik tymczasowy utworzony przez wykonanie operacji wymiany przy użyciu :(Pętla plików korzystająca z zastępowania procesów innymi niż POSIX i
read -d
obsługiwana npbash
. Przez .)źródło