Odpowiedzi:
sed -i 's/original/new/g' file.txt
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
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ści sed -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:
marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog
Innym sposobem, który może mieć większy sens niż < strin
i > strout
jest za pomocą rur!
marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai
The quick brown fox jumped over the lazy sleeping dog
cat
w cat 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ąc time 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:
roses are red , violets are blue
This is an input.txt and this doesn't rhyme
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}
.
#!/bin/bash
while IFS= read -r line
do
case "$line" in
*blue*) printf "%s\n" "${line/blue/azure}" ;;
*) printf "%s\n" "$line" ;;
esac
done < input.txt
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, 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()
i gsub()
. 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ów one potato two potato
, byłby to wynik:
$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana
$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'
one banana two potato
AWK może przyjmować plik wejściowy jako argument, więc robienie tych samych rzeczy input.txt
byłoby łatwe:
awk '{sub(/blue/,"azure")}1' input.txt
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:
awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt
Sed jest edytorem linii. Używa również wyrażeń regularnych, ale w przypadku prostych podstawień wystarczy wykonać:
sed 's/blue/azure/' input.txt
Zaletą tego narzędzia jest możliwość edycji w miejscu, którą można włączyć za pomocą -i
flagi.
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:
perl -pe 's/blue/azure/' input.txt
Podobnie jak sed, perl ma również flagę -i.
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:
python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt
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:
#!/usr/bin/env python
import sys
import os
import tempfile
tmp=tempfile.mkstemp()
with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
for line in fd1:
line = line.replace('blue','azure')
fd2.write(line)
os.rename(tmp[1],sys.argv[1])
Ten skrypt należy wywoływać input.txt
jako argument wiersza polecenia. Dokładna komenda do uruchomienia skryptu Pythona z argumentem wiersza poleceń to
$ ./myscript.py input.txt
lub
$ python ./myscript.py input.txt
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 ma re.sub()
funkcję, której można użyć do bardziej zaawansowanych zamian.
tr
polecenia w
tr
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ład tr abc cde
tłumaczyłby a
na c
, b
to d
. Różni się nieco od zastępowania całych słów, jak za pomocą sed
lubpython
Możesz używać Vima w trybie Ex:
ex -s -c '%s/OLD/NEW/g|x' file
%
wybierz wszystkie linie
s
zastąpić
g
zamień wszystkie wystąpienia w każdej linii
x
napisz, jeśli dokonano zmian (mają) i wyjdź
Poprzez polecenie gsub awk,
awk '{gsub(/pattern/,"replacement")}' file
Przykład:
awk '{gsub(/1/,"0");}' file
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,
awk '{gsub(/pattern/,"replacement",column_number)}' file
Przykład:
awk '{gsub(/1/,"0",$1);}' file
Zastępuje 1 z 0 tylko w pierwszej kolumnie.
Poprzez Perla,
$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
inotifywait
pod sh
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 co sed
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) przez sed
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 :
sed -i -e 's/few/asd/g' hello.txt
s/
stosuje się S ubstitute znaleziony ekspresji few
z asd
:
Nieliczni, odważni.
Asd, odważny.
/g
oznacza „globalny”, co oznacza, że należy to zrobić dla całej linii. Jeśli odrzucisz /g
(z s/few/asd/
, zawsze muszą być trzy ukośniki bez względu na wszystko) i few
pojawi się dwa razy w tej samej linii, tylko pierwsza few
zostanie zmieniona na asd
:
Tych niewielu mężczyzn, kilka kobiet, odważnych.
Asd mężczyźni, kilka kobiet, odważny.
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 pliku hello.txt
.
-e
Opcja wskazuje e Xpression / polecenie do uruchomienia, w tym przypadku s/
.
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”.
Możesz to zrobić w następujący sposób:
locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g"
Przykłady: aby zamienić wszystkie wystąpienia [logdir ',' '] (bez []) na [logdir', os.getcwd ()] we wszystkich plikach będących wynikiem polecenia locate, wykonaj:
ex1:
locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"
ex2:
locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"
gdzie [tensorboard / program.py] to plik do przeszukania
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.