Newlines w wersji na Mac OS X.

44

Uważam, że \nto nie działa w systemie Mac OS X. W szczególności powiedzmy, że chcę podzielić słowa oddzielone pojedynczą spacją na linie:

# input
foo bar

Używam,

echo "foo bar" | sed 's/ /\n/'

Ale wynik jest głupi, \nnie uciekł!

foonbar

Po konsultacji z Google znalazłem obejście :

echo 'foo bar' | sed -e 's/ /\'$'\n/g'

Po przeczytaniu artykułu nadal nie rozumiem, co \'$'\n/g'to znaczy. Czy ktoś może mi to wytłumaczyć lub czy istnieje inny sposób? Dzięki!

Ivan ZG Xiao
źródło
to też prawdopodobnie działałoby:echo "foo bar" | tr ' ' '\n'
glenn jackman
3
Dzięki za radę. Ale obecnie używam powyższego przypadku jako przykładu, muszę wiedzieć, jak uciec \n.
Ivan ZG Xiao,
Możliwy duplikat: stackoverflow.com/questions/21621722/…
hyiltiz 19.04.17

Odpowiedzi:

27

Można brew install gnu-sedi zastąpienie połączeń do sedz gsed.

Jeśli nie chcesz dodawać „g” do sed, możesz brew install gnu-sed --with-default-namesi po prostu zadzwoń sed.

(Edycja: zaktualizowano flagę naparu, wskazówkę do Clémenta.)

Ahmed Fasih
źródło
Używanie tego samego oprogramowania na wszystkich platformach jest (w końcu dla mnie) o wiele łatwiejsze niż zajmowanie się wszystkimi szczegółami wersji Mac. Uwaga, opcja jest teraz --with-default-namesi nie --default-names . Jednak opcja ta nie działa na mojej instalacji, więc musiałem umieścić alias gsed=sedw moim ~/.profile, aby to działało.
Clément
4
To brzydkie obejście. Nie wyjaśnia, dlaczego sedw OS X zachowuje się tak, jak robi, i sprawia, że ​​błędne założenie gnu-sedjest bardziej poprawne. Nie uzależniaj się od GNU i trzymaj się standardów POSIX, aby uniknąć problemów na dłuższą metę.
octosquidopus
Tak Apple powinien domyślnie sprawić, aby jego system operacyjny działał. Po co używać nazwy programu, a następnie sprawić, by działał inaczej?
Przez
@rascio - ponieważ OS X jest podobny do BSD, a Linux jest podobny do Linuksa.
iDodatek
@rascio Myślę, że przekonasz się, że GNU sed jest nowicjuszem; BSD sed pochodzi z 1979 roku (patrz en.wikipedia.org/wiki/Version_7_Unix ).
Duncan Bayne,
24

Te działałyby również:

echo 'foo bar' | sed 's/ /\
/g'

echo 'foo bar' | sed $'s/ /\\\n/g'

lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"

Sed OS X nie interpretuje \nwzorca zastępowania, ale można użyć dosłownego przesunięcia linii poprzedzonego znakiem kontynuacji linii. Powłoka zastępuje $'\n'dosłowny wysuw wiersza przed uruchomieniem polecenia sed.

Lri
źródło
4
Dlaczego sed $'s/ /\\\n/g'działa, ale nie sed $'s/\\\n/ /g'?
Alec Jacobson
1
@alec Nie możesz używać sednawet w linux / unix do usuwania nowych linii, ponieważ jest on analizowany / dzielony na każdej nowej linii. Jeśli uruchomisz to w Linuksie / echo -e 'foo\nbar' | sed 's/\n//'
Unixie,
10

Obejście, które znalazłeś, przekazuje ciąg jednego argumentu do sed -e.

Ten argument kończy się ciągiem w znanym s/ / /gformacie sed .

Ten ciąg jest tworzony w dwóch częściach, jedna po drugiej.

Pierwsza część jest cytowana w '...'formie.

Druga część jest cytowana w $'...'formie.

's/ /\'Część dostaje jednorazowego cytaty zdjął, ale w przeciwnym razie przechodzi do sed tak jak to wygląda na linii poleceń. Oznacza to, że ukośnik odwrotny nie jest zjadany przez uderzenie, jest przekazywany do sed.

$'\n/g'Część dostaje znak dolara i apostrofy zdjął, a \nzostanie przekonwertowany na znak nowej linii.

Wszystko razem staje się argumentem

s / / \ newline/ g

[To było zabawne. Zajęło to trochę czasu, aby to rozpakować. +1 za interesujące pytanie.]

Spiff
źródło
7

Wyrażenie $'...'to bash-izm, który wytwarza ...przy rozszerzonych standardowych sekwencjach ucieczki. Th \', zanim to tylko oznacza odwrotny ukośnik, po której następuje zakończenie cytowanego sekcji, otrzymany ciąg jest s/ /\. (Tak, możesz przełączać cytowanie w środku łańcucha; to nie kończy łańcucha).

Standard POSIX sedakceptuje tylko \njako część wzorca wyszukiwania. OS X używa FreeBSD sed, który jest ściśle zgodny z POSIX; GNU, jak zwykle, dodaje dodatkowe rzeczy, a potem użytkownicy Linuksa myślą, że jest to pewien rodzaj „standardu” (być może byłbym pod większym wrażeniem, gdyby któryś z nich miał standardową procedurę).

geekozaur
źródło
Teraz rozumiem tę $'...'część. Ale ... co to jest s/ /\ ? Co masz na myśli switch quoting?
Ivan ZG Xiao,
2
'...'jest jednym rodzajem cytowania powłoki; $'...'jest inny. Jest też "..."i \xzacytować jedną postać. Możesz łączyć je w jednym słowie, co właśnie tam robiono, przełączając się z normalnego ''łańcucha na $''łańcuch, aby przetłumaczyć \n. Jeśli chodzi o resztę, buduje sedpolecenie ( s/text/replacement/flags). W takim przypadku polecenie jest uruchamiane, w tym ukośnik odwrotny na końcu, aby chronić dosłowny znak nowej linii, który jest $'\n/g'dołączany. Rezultatem jest zastąpienie wszystkich /gspacji ( flag) nowymi liniami.
geekozaur
1

Bardzo łatwo jest wizualnie zobaczyć, co się dzieje. Po prostu powtórz ciąg znaków!

echo 's/$/\'$'\n/g'

prowadzi do

s/$/\
/g

co jest równoważne z s/$/\newline/g

Jeśli nie posiadasz dodatkowych \przed newline, powłoka zinterpretuje newlineprzedwcześnie koniec komendy.

wisbucky
źródło