Różnice między sedem w Mac OSX a innym „standardowym” sedem?

Odpowiedzi:

43

Zachowanie narzędzi powłoki różni się nieznacznie między wariantami unixa. Istnieje wiele wariantów uniksowych o złożonej historii . Podejmowanedziałania normalizacyjne, takie jak standard POSIX i jego nadzbiór nad specyfikacją Single UNIX . Obecnie większość systemów implementuje POSIX: 2001, znany również jako specyfikacja Single UNIX wersja 3 , z niewielkimi odchyleniami i wieloma rozszerzeniami. Specyfikacja Single Unix nie jest samouczkiem, ale wersja 3 jest czytelna, jeśli już wiesz, co robi polecenie. Możesz skonsultować się z nim, aby dowiedzieć się, czy jakaś funkcja jest standardem czy rozszerzeniem określonego systemu.

Większość użytkowników Uniksa używa Linuksa i nie użyła żadnego innego wariantu. Linux jest dostarczany z narzędziami GNU , które często mają wiele rozszerzeń standardu. Znajdziesz więc sporo kodu, który działa na Linuksie, ale nie na innych unikach, ponieważ opiera się na tych rozszerzeniach.

Jeśli chodzi o sed, zapoznaj się ze specyfikacją sed Single Unix, aby poznać minimum, które powinien obsługiwać każdy system, stronę podręcznika systemowego, która obsługuje implementację, oraz instrukcję GNU sed, z której korzysta większość osób.

Jedno z niestandardowych rozszerzeń GNU sed obsługuje wiele poleceń uruchamianych razem. Na przykład ten program GNU sed wypisuje wszystkie linie zawierające a, ale zmienia się bw cpierwszy:

sed -ne '/a/ {s/b/c/g; p}'

{i }tak naprawdę są osobnymi poleceniami, więc dla pełnej przenośności musisz je określić albo w osobnych wierszach (w pliku), albo w osobnych -eargumentach (w wierszu poleceń). Brak separatora poleceń po {i użycie ;jako separatora poleceń są powszechnymi rozszerzeniami. Brak separatora poleceń wcześniej }jest rzadszym rozszerzeniem. Jest to zgodne ze standardami:

sed -n -e '/a/ {' -e 's/b/c/g' -e p -e '}'

Jest to niestandardowe, ale powszechnie akceptowane:

sed -ne '/a/ { s/b/c/g; p; }'

Innym niestandardowym, ale powszechnym rozszerzeniem jest użycie \nznaku nowej linii w stekście zastępczym (użycie wyrażenia regularnego jest standardowe). Przenośną metodą jest uwzględnienie odwrotnego ukośnika w skrypcie sed. Innym powszechnym rozszerzeniem jest \+, \?a \|wyrażenia regularne oznacza jedno lub więcej, co najwyżej jedno i na przemian; w przenośnych podstawowych wyrażeniach regularnych nie ma żadnego z nich. Na przykład pierwsze polecenie jest nieprzenośnym sposobem zastępowania ciągłych sekwencji białych znaków nową linią; drugie polecenie jest odpowiednikiem zgodnym ze standardami.

sed -e 's/ \+/\n/'
sed -e 's/  */\
/'
Gilles
źródło
Zauważ, że we wszystkich tych przypadkach dotyczących rozszerzeń GNU jest to użycie niestandardowe. sedSam GNU jest zgodny, ponieważ pozwala na rzeczy dozwolone (ale nie wymagane, nieokreślone) przez standard. Są przypadki, w których jest niezgodny i gdzie POSIXLY_CORRECTmoże pomóc uruchomienie go w środowisku. Podobnie jak w przypadku s/[\n]//gtego, należy usunąć luz i nznaki, ale zamiast tego usunąć nowe linie. Lub zachowanie Npolecenia w ostatnim wierszu.
Stéphane Chazelas,
sed -ne '/a/ { s/b/c/g; p; }'jest standardem od wydania normy 2016. Zawsze był przenośny. Zobacz austingroupbugs.net/view.php?id=944&nbn=7
Stéphane Chazelas
60

OS X jest obecnie wyposażony w wersję FreeBSD sed z 2005 roku. Większość poniższych różnic dotyczy także innych wersji BSD sed.

Zastosowania sed OS X dla zastosowań -EERE i GNU sed -r. -Eto alias dla -rGNU sed (dodany w 4.2, nieudokumentowany do 4.3). Nowsze wersje FreeBSD i NetBSD sed obsługują zarówno -Ei -r. OpenBSD sed obsługuje tylko -E.

-i ''działa z sed OS X, ale nie z GNU sed. -iwspółpracuje z GNU sed, najnowszymi wersjami NetBSD, OpenBSD sed, ale nie sed OS X. -i -ewspółpracuje z obydwoma, ale w przypadku FreeBSD sedwykonuje kopię zapasową oryginalnego pliku z -edopisaniem do nazwy pliku (i musisz przekazać nie więcej niż jedno wyrażenie sed).

GNU sed interpretuje sekwencje, takie jak \t, \n, \001, \x01, \w, i \b. Sed OS X i POSIX sed interpretują tylko \n(ale nie w części zamiennej s).

GNU sed interpretuje \|, \+oraz \?w BRE ale sed i POSIX sed OS X za nie. \(, \), \{, I \}są POSIX BRE.

GNU sed pozwala na pomijanie ;lub nową linię wcześniej, }ale sed OS X nie.

i(wstaw), a(dołącz) i c(zmień) muszą być poprzedzone odwrotnym ukośnikiem i nową linią w sed OS X i POSIX sed, ale nie w GNU sed. Sed GNU dodaje brakujący przełamane po tekście włożonej przez i, alub cale OS X sed nie. Na przykład sed 1iajest GNU alternatywą dla sed $'1i\\\na\n'.

Na przykład printf a|sed -n pdodaje nową linię w sed OS X, ale nie w GNU sed.

Sed OS X nie obsługuje modyfikatorów I(bez uwzględniania wielkości liter) ani M(wielu linii). Nowsze wersje wsparcia dla FreeBSD sed I.

Sed OS X nie obsługuje -s( --separate), -u( --unbuffered) ani -z( --null-data).

Jedną z opcji BSD, która nie jest obsługiwana przez GNU sed -a, jest wdodanie pliku do pliku zamiast obcięcia go.

Przykłady poleceń GNU sed, które nie działają z sed OS X:

sed /pattern/,+2d # like `sed '/pattern/{N;N;d;}'`
sed -n 0~3p # like `awk NR%3==0`
sed /pattern/Q # like `awk '/pattern/{exit}1'` or `sed -n '/pattern/,$!p'`
sed 's/\b./\u&/g' # \u converts the next character to uppercase
sed 's/^./\l&/' # \l converts the next character to lowercase
sed -i '1ecat file_to_prepend' file # e executes a shell command
sed -n l0 # 0 disables wrapping
Lri
źródło
4
-i -enie działa na OSX. Interetuje -ejako przyrostek.
Chris Martin
3
@ChrisMartin tak, w wersji OS X -izawsze wymaga sufiksu, nawet jeśli pusty ciąg. tak -i '' -epowinno działać.
waldyrious
@waldyrious Działa tylko na OSX.
Chris Martin
tak, to dziwactwo tej wersji :)
waldyrious
3
Zdanie „ -i -edziała z oboma”. w twojej odpowiedzi sugeruje, że istnieje rozwiązanie wieloplatformowe. Najwyraźniej nie ma.
leondepeon
5

Najlepszym sposobem, w jaki znalazłem taką samą pracę skryptów w systemach Linux i Mac jest:

sed -i.bak -e 's/foo/bar/' -- "${TARGET}" &&
  rm -- "${TARGET}.bak"
Vikrantt
źródło
Lub użyj perlskąd -ipochodzi. perl -Tpi -e 's/foo/bar/' -- "$TARGET"
Stéphane Chazelas