W moim projekcie wymagam zastąpienia istniejącego tekstu w pliku, takim jak foo
innym tekstem, takim jak fooofoo
:
abc.txt
name
foo
foo1
Więc próbowałem:
sed -i "s/foo/fooofoo/g" abc.txt
Jednak pojawia się ten błąd:
sed: nielegalna opcja -
i
W instrukcji znalazłem, że muszę użyć:
sed -i\ "s/foo/fooofoo/g" abc.txt
Jednak to też nie działa.
Znalazłem w alternatywnych perl
i awk
też ale to rozwiązanie w Solaris sed
będą mile widziane.
Korzystam z tej wersji bash:
GNU bash, wersja 3.2.57 (1) -release (sparc-sun-solaris2.10)
text-processing
sed
solaris
tpsaitwal
źródło
źródło
/usr/gnu/bin/sed
aby uzyskać obsługę -i.Odpowiedzi:
Zastosowanie
ed
. Jest dostępny na większości platform i może edytować pliki w miejscu.Ponieważ
sed
opiera sięed
na składni zastępowania wzorców jest podobny:źródło
ed
zamiast poex
prostu ciekawy? (Wiem, że oba są zgodne z POSIX i podłączyłem do specyfikacji.;))ex
? Aby odpowiedzieć na twoje pytanie: ponieważ nigdyex
nie używam, nie znam go. btw, widziałem konfiguracje, w któryched
był obecny, aleex
nie był (ale nie odwrotnie) ... najbardziej zauważalny jest mój laptop :)ex
polecenia. Wszystkievi
polecenia, które można wpisać zaczynające się dwukropkiem, sąex
poleceniami. Istnieje oczywiście kilka rozszerzeń specyficznych dla Vima, ale tylko podstawowy zestaw poleceń jest niewiarygodnie wydajny i elastyczny i jest wystarczający do edytowania skryptów.ex
a jeszcze nie maed
.Jeśli nie możesz zainstalować GNU sed, użyj:
Używa przekierowania, aby wysłać dane wyjściowe sed do pliku tymczasowego. Jeśli sed zakończy się powodzeniem, to zastąpi
abc.txt
to plik tymczasowy.Jak widać z kodu źródłowego GNU sed , właśnie to
sed -i
robi. Jest to więc tak samo wydajne jaksed -i
.Jeśli istnieje już szansa
abc.tmp
, możesz użyćmktemp
lub podobnego narzędzia do wygenerowania unikalnej nazwy tymczasowej.źródło
ed
, ponieważ wczytuje cały plik do pamięci.Jeśli chcesz ekwiwalent
sed -i.bak
, jest to dość proste.Rozważ ten skrypt dla GNU sed:
Możemy po prostu zamienić zaznaczoną linię na
To przenosi istniejący plik jako kopię zapasową i zapisuje nowy plik.
Jeśli chcemy odpowiednika
to jest nieco bardziej złożone. Możemy otworzyć plik do odczytu jako standardowe wejście, a następnie rozłączyć go, zanim wydamy polecenie sed w celu zastąpienia:
Robimy to w podpowłoce, aby nasz oryginalny stdin był nadal dostępny po tym. Możliwe jest przełączanie wejść i przełączanie z powrotem bez podpowłoki, ale ten sposób wydaje mi się jaśniejszy.
Pamiętaj, że staramy się najpierw skopiować, a nie utworzyć nowy
foo
plik - jest to ważne, jeśli plik jest znany pod więcej niż jedną nazwą (tzn. Ma twarde linki) i chcesz mieć pewność, że nie zerwiesz linków .źródło
Po pierwsze, powinieneś wiedzieć, że
i\
polecenie, do którego się odwołujesz, służy do wstawiania wiersza tekstu - a nie do zapisywania edytowanego tekstu z powrotem do pliku. Nie ma POSIX określony sposób użyćsed
do tego.Co można zrobić, to użyć
ex
, który jest określony przez POSIX :x
Komenda jest na „zapisz i wyjdź”. Możesz także użyć,wq
alex
jest krótszy.%
Znak na początku środki dowodzenia substytutem „Zastosuj tego polecenia do każdej linii w buforze.” Możesz1,$s/find/replace/g
także użyć .Jedną z głównych różnic między
ex
ised
jest to, żesed
jest edytorem strumieniowym . Działa tylko sekwencyjnie, linia po linii.ex
jest o wiele bardziej elastyczny i można bezpośrednio edytować interaktywny plik tekstowyex
. Jest bezpośrednim poprzednikiemvi
.źródło
Używanie
sed
i brak widocznego pliku tymczasowego:Możesz uniknąć tworzenia osobnego widocznego „pliku tymczasowego”:
Wyjaśnienie
Uniksowych systemów rzeczywistości nie usunąć zawartość pliku z dysku aż nadszedł zarówno odłączone w systemie plików, a nie otworzyć w innym procesie. Więc możesz zrobić,
exec 3<
aby otworzyć plik w powłoce w celu odczytania na deskryptorze pliku 3,rm
pliku (który odłącza go od systemu plików), a następnie wywołać zased
pomocą deskryptora pliku 3 używanego jako jego dane wejściowe.Pamiętaj, że jest to bardzo różne od tego:
Różnica polega na tym, że gdy zrobisz to za pomocą jednego polecenia, powłoka po prostu otwiera ten sam plik zarówno do odczytu, jak i do zapisu z opcją obcięcia pliku - ponieważ nadal jest to ten sam plik, tracisz zawartość. Ale jeśli otworzysz go do odczytu, a następnie
rm
, a następnie otworzysz tę samą ścieżkę do zapisu, tak naprawdę tworzysz nowy plik pod tą samą ścieżką (ale w nowej lokalizacji i-węzła i lokalizacji dysku, ponieważ oryginał jest nadal otwarty): więc zawartość jest nadal dostępna.Następnie, gdy skończysz, możesz zamknąć deskryptor pliku, który wcześniej otworzyłeś (to robi
exec 3<&-
specjalna składnia), co zwalnia oryginalny plik, aby system operacyjny mógł usunąć (oznaczyć jako nieużywany) swoje miejsce na dysku.Ostrzeżenia
O tym rozwiązaniu należy pamiętać:
Dostajesz tylko jedno „przejście” przez zawartość - nie ma przenośnego sposobu, aby powłoka „szukała” z powrotem w deskryptorze pliku - więc gdy program odczyta część zawartości, inne programy zobaczą tylko resztę pliku. I
sed
przeczyta cały plik.Istnieje niewielka szansa na utratę oryginalnego pliku, jeśli twoja powłoka / skrypt / sed zostanie zabita, zanim zostanie wykonana.
źródło
perl -i
to kolejna dobra opcja. Pytanie dotyczyło w szczególności rozwiązania zgodnego z Solarissed
, w przeciwieństwie do rozwiązań zperl
iawk
o których wspominali już o znalezieniu. Ponadto moja odpowiedź miała głównie na celu dodanie czegoś, co moim zdaniem było przydatne i którego nie znam w żadnej z pozostałych odpowiedzi.