Edycja lokalna za pomocą seda na OS X


142

Chciałbym edytować plik za pomocą seda na OS X. Używam następującego polecenia:

sed 's/oldword/newword/' file.txt

Wyjście jest wysyłane do terminala. plik.txt nie jest modyfikowany. Zmiany są zapisywane w pliku file2.txt za pomocą tego polecenia:

sed 's/oldword/newword/' file1.txt > file2.txt

Jednak nie chcę innego pliku. Chcę tylko edytować plik1.txt . W jaki sposób mogę to zrobić?

Wypróbowałem flagę -i. Powoduje to następujący błąd:

sed: 1: "file1.txt": invalid command code f

2
Jakiego dokładnie polecenia używasz, próbując -iflagi?
eldarerathis

Odpowiedzi:


282

Możesz użyć -iflagi poprawnie, podając sufiks, który zostanie dodany do pliku kopii zapasowej. Rozszerzając twój przykład:

sed -i.bu 's/oldword/newword/' file1.txt

Otrzymasz dwa pliki: jeden z nazwą file1.txtzawierającą podstawienie i jeden z nazwą file1.txt.buzawierającą oryginalną zawartość.

Lekko niebezpieczne

Jeśli chcesz destrukcyjnie nadpisać oryginalny plik, użyj czegoś takiego:

sed -i '' 's/oldword/newword/' file1.txt
      ^ note the space

Ze względu na sposób analizowania wiersza wymagana jest spacja między flagą opcji a jej argumentem, ponieważ argument ma zerową długość.

Poza ewentualnym zniszczeniem oryginału, nie jestem świadomy dalszych niebezpieczeństw związanych z oszukaniem seda w ten sposób. Należy jednak zauważyć, że jeśli to wywołanie programu sedjest częścią skryptu, system Unix Way ™ (IMHO) powinien użyć funkcji sednieniszczącej, przetestować, czy zakończył się poprawnie, a dopiero potem usunąć zbędny plik.


Masz rację, pominąłem rozszerzenie po fladze -i. Czy jest -i''niebezpieczny z jakiegokolwiek innego powodu niż potencjalne zepsucie oryginalnego pliku (i brak kopii zapasowej)?
Niedziela, poniedziałek,

Zgodnie ze sedstroną podręcznika, jeśli zabraknie miejsca na dysku w urządzeniu, możesz uszkodzić plik w trakcie kroku i uzyskać zły wynik wyjściowy. Jeśli pracujesz pod kontrolą lokalnego źródła sed -i ""bez kopii zapasowych, powinno być dobrze przez większość czasu (lub tuż git init && git add -A . && git commit -m 'backup'przed uruchomieniem seda w -itrybie).
cfeduke

2
Uważam, że lekko niebezpieczny kawałek jest szczególnie przydatny. +1
Andre

5
Sed BSD wymaga, aby po fladze -i nie było spacji. Tak więc -i''jest ważny, ale -i ''nie jest.
Todd A. Jacobs

3
Argh! Sed z BSD ignoruje znak '\ n' i zamiast tego wypisuje 'n'! Zamierzam tylko zamienić sed BSD na sed GNU na moim Macu!
nterry

20

Mam podobny problem z MacOS

sed -i '' 's/oldword/newword/' file1.txt

nie działa, ale

sed -i"any_symbol" 's/oldword/newword/' file1.txt

działa dobrze.


Teraz jest na odwrót. sed -i '' <file>działa, ale sed -i'' <file>już nie działa
Zohaib Amanzai


4

Możesz użyć -i''( --in-place) sedjak już sugerowano. Zobacz: Argument -iw miejscu , zwróć jednak uwagę, że -iopcja jest niestandardowym rozszerzeniem FreeBSD i może nie być dostępna w innych systemach operacyjnych. Po drugie sedjest to itor S tream ED , a nie edytor plików .


Alternatywnym sposobem jest użycie wbudowanego podstawiania w trybie Vim Ex, na przykład:

$ ex +%s/foo/bar/g -scwq file.txt

a dla wielu plików:

$ ex +'bufdo!%s/foo/bar/g' -scxa *.*

Aby edytować wszystkie pliki rekurencyjnie, możesz użyć **/*.*jeśli powłoka to obsługuje (włącz przez shopt -s globstar).


Innym sposobem jest użycie gawki jego nowego rozszerzenia „inplace”, takiego jak:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1

4

Tworzy to pliki kopii zapasowych. Np. sed -i -e 's/hello/hello world/' testfileDla mnie tworzy plik kopii zapasowej, testfile-e, w tym samym katalogu.


To samo dotyczy Mac OS Catalina. Przekazanie zarówno -i, jak i -e osobno (NIE -ie razem!) Tworzy plik kopii zapasowej z dołączonym '-e'.
Daniel Kesner

1

Możesz użyć:

sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>

Przykład:

sed -i -e 's/Hello/Bye/' file.txt

Działa to bezbłędnie na komputerach Mac .


2
Spowoduje to utworzenie dla mnie pliku kopii zapasowej w systemie Mac OS Catalina z dołączonym „-e”.
Daniel Kesner

To jest złe dla macOS. Proszę spojrzeć na stronę „man sed”. -iwymaga argumentu dla macOS. Ponieważ nie określisz żadnego, używa -e, co skutkuje posiadaniem drugiego pliku z -edołączonym. -enie istnieje w macOS, tak jest -E. Tak więc poprawne polecenie dla macOS tosed -i '' -E 's/Hello/Bye/' file.txt
Marc J. Schmidt
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.