Uważam, że \n
to 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, \n
nie 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!
echo "foo bar" | tr ' ' '\n'
\n
.Odpowiedzi:
Można
brew install gnu-sed
i zastąpienie połączeń dosed
zgsed
.Jeśli nie chcesz dodawać „g” do
sed
, możeszbrew install gnu-sed --with-default-names
i po prostu zadzwońsed
.(Edycja: zaktualizowano flagę naparu, wskazówkę do Clémenta.)
źródło
--with-default-names
i nie--default-names
. Jednak opcja ta nie działa na mojej instalacji, więc musiałem umieścićalias gsed=sed
w moim~/.profile
, aby to działało.sed
w OS X zachowuje się tak, jak robi, i sprawia, że błędne założeniegnu-sed
jest bardziej poprawne. Nie uzależniaj się od GNU i trzymaj się standardów POSIX, aby uniknąć problemów na dłuższą metę.Te działałyby również:
echo 'foo bar' | sed $'s/ /\\\n/g'
lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"
Sed OS X nie interpretuje
\n
wzorca 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.źródło
sed $'s/ /\\\n/g'
działa, ale niesed $'s/\\\n/ /g'
?sed
nawet 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//'
Obejście, które znalazłeś, przekazuje ciąg jednego argumentu do
sed -e
.Ten argument kończy się ciągiem w znanym
s/ / /g
formacie 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\n
zostanie 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.]
źródło
Wyrażenie
$'...'
tobash
-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 jests/ /\
. (Tak, możesz przełączać cytowanie w środku łańcucha; to nie kończy łańcucha).Standard POSIX
sed
akceptuje tylko\n
jako część wzorca wyszukiwania. OS X używa FreeBSDsed
, 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ę).źródło
$'...'
część. Ale ... co to jests/ /\
? Co masz na myśliswitch quoting
?'...'
jest jednym rodzajem cytowania powłoki;$'...'
jest inny. Jest też"..."
i\x
zacytować 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ę, budujesed
polecenie (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/g
spacji ( flag) nowymi liniami.Bardzo łatwo jest wizualnie zobaczyć, co się dzieje. Po prostu powtórz ciąg znaków!
prowadzi do
co jest równoważne z
s/$/\
newline/g
Jeśli nie posiadasz dodatkowych
\
przednewline
, powłoka zinterpretujenewline
przedwcześnie koniec komendy.źródło