Jak znaleźć i zamienić określone słowa w pliku tekstowym za pomocą wiersza poleceń?
command-line
text-processing
Jon Doe
źródło
źródło
Odpowiedzi:
Wyjaśnienie:
sed
= Edytor strumienia-i
= w miejscu (tj. zapisz z powrotem do oryginalnego pliku)Ciąg poleceń:
s
= polecenie zastępczeoriginal
= wyrażenie regularne opisujące słowo do zastąpienia (lub tylko samo słowo)new
= tekst, który ma go zastąpićg
= globalny (tzn. zastąp wszystkie, a nie tylko pierwsze wystąpienie)file.txt
= nazwa plikuźródło
sed
będą do nich pasować. Dodaj-r
flagę, jeśli zamiast tego chcesz użyć rozszerzonych elementów RE./
znak, który musisz dopasować, możesz po prostu użyć innego znaku jako separatora (np's_old/text_new/text_g'
.). W przeciwnym razie możesz postawić\
przed dowolnym z nich,$ * . [ \ ^
aby uzyskać dosłowny charakter.sed -i '.bak' 's/original/new/g' file.txt
można również uruchomić z rozszerzeniem zerowej długoścised -i '' 's/original/new/g' file.txt
, które nie wygeneruje kopii zapasowej.Można to zrobić na wiele różnych sposobów. Jeden używa
sed
i Regex. SED to Edytor strumienia do filtrowania i przekształcania tekstu. Jeden przykład jest następujący:Innym sposobem, który może mieć większy sens niż
< strin
i> strout
jest za pomocą rur!źródło
cat
wcat file | sed '...'
to niepotrzebne. Możesz bezpośrednio powiedziećsed '...' file
.sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly
weźmie plik i wykona 2 zmiany w miejscu podczas tworzenia kopii zapasowej. Używająctime bash -c "$COMMAND"
czasu sugeruje, że ta wersja jest ~ 5 razy szybsza.Istnieje wiele sposobów na osiągnięcie tego. W zależności od złożoności tego, co próbuje się osiągnąć za pomocą zamiany łańcucha, oraz w zależności od narzędzi, z którymi użytkownik jest zaznajomiony, niektóre metody mogą być preferowane bardziej niż inne.
W tej odpowiedzi używam prostego
input.txt
pliku, którego można użyć do przetestowania wszystkich podanych tutaj przykładów. Zawartość pliku:GRZMOTNĄĆ
Bash nie jest tak naprawdę przeznaczony do przetwarzania tekstu, ale proste podstawienia można wykonać poprzez rozszerzenie parametrów , w szczególności tutaj możemy użyć prostej struktury
${parameter/old_string/new_string}
.Ten mały skrypt nie zastępuje w miejscu, co oznacza, że musisz zapisać nowy tekst w nowym pliku i pozbyć się starego pliku lub
mv new.txt old.txt
Uwaga dodatkowa: jeśli jesteś ciekawy, dlaczego
while IFS= read -r ; do ... done < input.txt
jest używany, jest to po prostu sposób czytania pliku wiersz po wierszu. Zobacz to w celach informacyjnych.AWK
AWK, jako narzędzie do przetwarzania tekstu, jest całkiem odpowiednie do takiego zadania. Może dokonywać prostych zamian i znacznie bardziej zaawansowanych na podstawie wyrażeń regularnych . Zapewnia dwie funkcje:
sub()
igsub()
. Pierwszy zastępuje tylko pierwsze wystąpienie, a drugi - zastępuje wystąpienia całym ciągiem. Na przykład, jeśli mamy ciąg znakówone potato two potato
, byłby to wynik:AWK może przyjmować plik wejściowy jako argument, więc robienie tych samych rzeczy
input.txt
byłoby łatwe:W zależności od wersji AWK, którą posiadasz, może ona mieć lub nie mieć edycji na miejscu, dlatego zwykłą praktyką jest zapisywanie i zastępowanie nowego tekstu. Na przykład coś takiego:
SED
Sed jest edytorem linii. Używa również wyrażeń regularnych, ale w przypadku prostych podstawień wystarczy wykonać:
Zaletą tego narzędzia jest możliwość edycji w miejscu, którą można włączyć za pomocą
-i
flagi.Perl
Perl to kolejne narzędzie, które jest często używane do przetwarzania tekstu, ale jest językiem ogólnego przeznaczenia i jest używane w sieci, administracji systemem, aplikacjach komputerowych i wielu innych miejscach. Pożyczył wiele pojęć / funkcji z innych języków, takich jak C, sed, awk i innych. Prostą zamianę można wykonać w następujący sposób:
Podobnie jak sed, perl ma również flagę -i.
Pyton
Ten język jest bardzo wszechstronny i jest również używany w wielu różnych aplikacjach. Ma wiele funkcji do pracy z łańcuchami, wśród których jest
replace()
, więc jeśli masz zmienną podobnąvar="Hello World"
, możesz to zrobićvar.replace("Hello","Good Morning")
Prostym sposobem na odczytanie pliku i zastąpienie w nim ciągu byłoby tak:
Jednak w Pythonie musisz także wyprowadzać dane do nowego pliku, co możesz również zrobić w samym skrypcie. Na przykład oto prosty:
Ten skrypt należy wywoływać
input.txt
jako argument wiersza polecenia. Dokładna komenda do uruchomienia skryptu Pythona z argumentem wiersza poleceń tolub
Oczywiście upewnij się, że
./myscript.py
znajduje się on w bieżącym katalogu roboczym i po pierwsze upewnij się, że jest ustawiony na plik wykonywalnychmod +x ./myscript.py
Python może również mieć wyrażenia regularne, w szczególności jest
re
moduł, który mare.sub()
funkcję, której można użyć do bardziej zaawansowanych zamian.źródło
tr
polecenia wtr
jest kolejnym doskonałym narzędziem, ale należy pamiętać, że służy on do zastępowania zestawów znaków (na przykładtr abc cde
tłumaczyłbya
nac
,b
tod
. Różni się nieco od zastępowania całych słów, jak za pomocąsed
lubpython
Możesz używać Vima w trybie Ex:
%
wybierz wszystkie linies
zastąpićg
zamień wszystkie wystąpienia w każdej liniix
napisz, jeśli dokonano zmian (mają) i wyjdźźródło
Poprzez polecenie gsub awk,
Przykład:
W powyższym przykładzie wszystkie 1 są zastępowane przez 0 bez względu na kolumnę, w której się znajdują.
Jeśli chcesz zrobić zamianę w określonej kolumnie, zrób tak,
Przykład:
Zastępuje 1 z 0 tylko w pierwszej kolumnie.
Poprzez Perla,
źródło
inotifywait
podsh
env, a dane w formacie CSV raportowanie (bo Format niestandardowy jest wadliwy). Uznałem wtedy, że nie ma prostego sposobu obsługi dokumentu CSV w skryptach powłoki ... I chcę, żeby był bardzo lekki. Więc zacząłem dość prosty skrypt do analizowania i raportowania CSV. Przeczytałem specyfikację CSV i zauważyłem, że jest bardziej rozbudowana niż się spodziewałem i obsługuje wartość wielowierszową opakowaną w podwójne cudzysłowy. Byłem powołując sięsed
na tokeny, ale szybko zorientował się, że nawet cosed
multilinie zadzwonić wynosi do dwóch linii. Co wtedy, gdy jedna z moich wartości CSV obejmuje więcej niż dwie linie?sed
jest s TREAM ed itor , w których można użyć|
(rury) do wysyłania standardowych strumieni (stdin i stdout konkretnie) przezsed
i zmieniać je programowo w locie, co czyni go przydatnym narzędziem w tradycji filozofii Unix; ale może również edytować pliki bezpośrednio, używając-i
parametru wymienionego poniżej.Rozważ następujące kwestie :
s/
stosuje się S ubstitute znaleziony ekspresjifew
zasd
:/g
oznacza „globalny”, co oznacza, że należy to zrobić dla całej linii. Jeśli odrzucisz/g
(zs/few/asd/
, zawsze muszą być trzy ukośniki bez względu na wszystko) ifew
pojawi się dwa razy w tej samej linii, tylko pierwszafew
zostanie zmieniona naasd
:Jest to przydatne w niektórych okolicznościach, na przykład zmieniając znaki specjalne na początku wiersza (na przykład zastępując symbole większe niż niektóre osoby używają do cytowania poprzedniego materiału w wątkach wiadomości e-mail za pomocą poziomej tabulacji, pozostawiając cytowaną nierówność algebraiczną później w wierszu nietknięte), ale w twoim przykładzie, w którym określasz, że gdziekolwiek
few
występuje, należy go wymienić, upewnij się, że go masz/g
.Następujące dwie opcje (flagi) są połączone w jedną
-ie
:-i
Opcja ta służy do edycji i n umieścić w plikuhello.txt
.-e
Opcja wskazuje e Xpression / polecenie do uruchomienia, w tym przypadkus/
.Uwaga: Ważne jest, aby używać
-i -e
do wyszukiwania / zastępowania. Jeśli to zrobisz-ie
, utworzysz kopię zapasową każdego pliku z dołączoną literą „e”.źródło
Możesz to zrobić w następujący sposób:
Przykłady: aby zamienić wszystkie wystąpienia [logdir ',' '] (bez []) na [logdir', os.getcwd ()] we wszystkich plikach będących wynikiem polecenia locate, wykonaj:
ex1:
ex2:
gdzie [tensorboard / program.py] to plik do przeszukania
źródło
logdir', ''
->/logdir', os.getcwd()
) sprawia, że odpowiedź jest trudna do przeanalizowania. Warto również określić, że twoja odpowiedź najpierw lokalizuje pliki, na których ma być używany sed, ponieważ nie jest to częścią pytania.