Czy istnieje wywołanie sed
edycji miejscowej todo bez kopii zapasowych, która działa zarówno w systemie Linux, jak i Mac? Podczas gdy BSD sed
dostarczany z OS X wydaje się być potrzebny sed -i '' …
, sed
dystrybucje GNU Linux zwykle zawierają interpretację cytatów jako pustą nazwę pliku wejściowego (zamiast rozszerzenia kopii zapasowej) i sed -i …
zamiast tego potrzebuje .
Czy jest jakaś składnia wiersza poleceń, która działa z oboma smakami, więc mogę używać tego samego skryptu w obu systemach?
Odpowiedzi:
Jeśli naprawdę chcesz po prostu użyć
sed -i
„łatwego” sposobu, poniższe DOES działają zarówno na GNU, jak i BSD / Macsed
:Zwróć uwagę na brak miejsca i kropkę.
Dowód:
Oczywiście możesz po prostu usunąć
.bak
pliki.źródło
sed
)sed
nie akceptuje pozycyjnącommand
argumentu przy wywołaniu z-i
- to musi być dostarczony z inną flagą-e
. Zatem polecenie staje się:sed -i.bak -e 's/foo/bar/' filename
sed -i.bak 's/foo/bar/' file && rm file.bak
Działa to z GNU sed, ale nie w OS X:
Działa to w OS X, ale nie w GNU sed:
W systemie OS X ty
sed -i -e
ponieważ rozszerzenie pliku kopii zapasowej byłoby ustawione na-e
sed -i'' -e
z tych samych powodów - potrzebuje odstępu między-i
i''
.źródło
-i
i-i''
są identyczne w czasie analizy powłoki;sed
nie może zachowywać się inaczej w przypadku tych dwóch pierwszych wywołań, ponieważ otrzymuje dokładnie te same argumenty.W systemie OSX zawsze instaluję wersję GNU sed przez Homebrew, aby uniknąć problemów ze skryptami, ponieważ większość skryptów została napisana dla wersji GNU sed.
Wtedy twój BSD sed zostanie zastąpiony przez GNU sed.
Alternatywnie możesz zainstalować bez domyślnych nazw, ale następnie:
PATH
zgodnie z instrukcją po instalacjignu-sed
gsed
lub wsed
zależności od systemuźródło
--with-default-names
został usunięty z homebrew-core , więcej informacji w tej odpowiedzi. podczas instalacjignu-sed
teraz, instrukcje instalacji określają, że musisz dodaćgnubin
doPATH
:PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Jak pyta Noufal Ibrahim , dlaczego nie możesz używać Perla? Każdy komputer Mac będzie miał Perla i istnieje bardzo niewiele dystrybucji Linuksa lub BSD, które nie zawierają niektórych wersji Perla w systemie podstawowym. Jednym z niewielu środowisk, w których może brakować Perla, byłby BusyBox (który działa jak GNU / Linux
-i
, z wyjątkiem tego, że nie można określić rozszerzenia kopii zapasowej).Jak zaleca ismail ,
i wydaje się to lepszym rozwiązaniem w prawie każdym przypadku niż skrypty, aliasy lub inne obejścia, aby poradzić sobie z podstawową niezgodnością
sed -i
między GNU / Linux a BSD / Mac.źródło
perl
jest częścią specyfikacji Linux Standard Base od 1 maja 2009 r. refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Languages/...Nie ma sposobu, aby działało.
Jednym ze sposobów jest użycie pliku tymczasowego, takiego jak:
Działa to w obu przypadkach
źródło
Odpowiedź: Nie.
Oryginalnie zaakceptowana odpowiedź tak naprawdę nie spełnia wymagań (jak zaznaczono w komentarzach). (Znalazłem tę odpowiedź, gdy szukałem powodu, dla którego a
file-e
pojawiał się „losowo” w moich katalogach).Najwyraźniej nie ma sposobu
sed -i
na konsekwentną pracę na MacOS i Linuces.Zalecam, aby nie warto aktualizować w miejscu
sed
(które ma złożone tryby awarii), ale generować nowe pliki i zmieniać ich nazwy później. Innymi słowy: unikaj-i
.źródło
Ta
-i
opcja nie jest częścią POSIX Sed . Bardziej przenośną metodą byłoby użycie Vima w trybie Ex:%
wybierz wszystkie linies
zastąpićx
Zapisz i zamknijźródło
Oto kolejna wersja, która działa w systemie Linux i macOS bez użycia
eval
i bez konieczności usuwania plików kopii zapasowej. Używa tablic Bash do przechowywaniased
parametrów, co jest czystsze niż przy użyciueval
:Nie tworzy to pliku kopii zapasowej ani pliku z dołączonymi cytatami.
źródło
sedi=(-i) && [ "$(uname)" == "Darwin" ] && sedi=(-i '')
sed "${sedi[@]}" -e 's/foo/bar/' target.file
Odpowiedź Steve'a Powella jest całkiem poprawna, zapoznanie się ze stroną MAN dla sed w OSX i Linux (Ubuntu 12.04) podkreśla niezgodność w zakresie użycia sed w „miejscu” w obu systemach operacyjnych.
JFYI, nie powinno być spacji między -i i dowolnymi cudzysłowami (które oznaczają puste rozszerzenie pliku) przy użyciu sed wersji Linux, więc
sed Linux Man Page
i
sed Strona podręcznika OSX
Obejrzałem to w skrypcie, używając komendy alias'd i wyjścia nazwy systemu operacyjnego „ uname ” w ciągu bash „if”. Próba przechowywania ciągów poleceń zależnych od systemu operacyjnego w zmiennych była trafiona i pominięta podczas interpretacji cudzysłowów. Użycie „ shopt -s expand_aliases ” jest konieczne, aby rozwinąć / użyć aliasów zdefiniowanych w skrypcie. wykorzystanie shopt jest omówione tutaj .
źródło
Jeśli trzeba zrobić
sed
na miejscu wbash
skrypcie, a ty nie chcesz, aby w miejscu spowoduje z plikami .bkp i masz sposób na wykrycie OS (powiedzmy, korzystając ostype.sh ) - wtedy następujący hack zbash
wbudowaną powłokąeval
powinien działać:źródło
Możesz użyć gąbki. Sponge to stary program uniksowy, znajdujący się w pakiecie moreutils (zarówno w Ubuntu i prawdopodobnie Debianie, jak i homebrew w Macu).
Buforuje całą zawartość z potoku, poczekaj, aż potok się zamknie (prawdopodobnie oznacza to, że plik wejściowy jest już zamknięty), a następnie zastąpi:
Od strony man :
źródło
Poniższe działa dla mnie w systemach Linux i OS X:
sed -i' ' <expr> <file>
np. dla pliku
f
zawierającegoaaabbaaba
sed -i' ' 's/b/c/g' f
daje
aaaccaaca
zarówno Linux, jak i Mac. Zauważ, że istnieje cytowany ciąg zawierający spację , bez spacji między nim-i
a ciągiem. Oba pojedyncze lub podwójne cudzysłowy działają.W systemie Linux używam
bash
wersji 4.3.11 pod Ubuntu 14.04.4, a Mac wersji 3.2.57 pod OS X 10.11.4 El Capitan (Darwin 15.4.0).źródło
Wpadłem na ten problem. Jedynym szybkim rozwiązaniem było zastąpienie sed w mac do wersji GNU:
źródło