Acho que \n
isso não funciona no sed no Mac OS X. Especificamente, digamos que quero dividir as palavras separadas por um único espaço em linhas:
# input
foo bar
Eu uso,
echo "foo bar" | sed 's/ /\n/'
Mas o resultado é estúpido, o \n
não é escapado!
foonbar
Depois de consultar o google, encontrei uma solução alternativa :
echo 'foo bar' | sed -e 's/ /\'$'\n/g'
Depois de ler o artigo, ainda não consigo entender o que \'$'\n/g'
significa. Alguém pode me explicar ou se existe alguma outra maneira de fazer isso? Obrigado!
echo "foo bar" | tr ' ' '\n'
\n
.Respostas:
Você pode
brew install gnu-sed
substituir as chamadassed
porgsed
.Se não quiser acrescentar o "g" a
sed
, você podebrew install gnu-sed --with-default-names
e basta ligarsed
.(Editar: bandeira de infusão atualizada, dica de chapéu para Clément.)
fonte
--with-default-names
e não--default-names
. No entanto, essa opção não funcionou na minha instalação, então tive que colocar umalias gsed=sed
no meu~/.profile
para fazê-lo funcionar.sed
OS X se comporta da maneira que faz e assume a suposição incorretagnu-sed
mais correta. Não seja viciado em GNU e siga os padrões POSIX para evitar problemas a longo prazo.Isso também funcionaria:
echo 'foo bar' | sed $'s/ /\\\n/g'
lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"
O sed do OS X não interpreta
\n
no padrão de substituição, mas você pode usar um avanço de linha literal precedido por um caractere de continuação de linha. O shell substitui$'\n'
por um avanço de linha literal antes do comando sed ser executado.fonte
sed $'s/ /\\\n/g'
funciona, mas nãosed $'s/\\\n/ /g'
?sed
nem no linux / unix para remover novas linhas porque elas são analisadas / divididas em cada nova linha. Se você executar este em linux / unix, ele não vai fazer nada também:echo -e 'foo\nbar' | sed 's/\n//'
A solução alternativa que você encontrou passa uma única sequência de argumentos para
sed -e
.Esse argumento acaba sendo uma string no
s/ / /g
formato sed familiar .Essa sequência é criada em duas partes, uma após a outra.
A primeira parte é citada no
'...'
formulário.A segunda parte é citada no
$'...'
formulário.A
's/ /\'
parte retira as aspas simples, mas passa para sed assim como aparece na linha de comando. Ou seja, a barra invertida não é comida pelo bash, é passada para sed.A
$'\n/g'
peça obtém o sinal de cifrão e as aspas simples, e\n
é convertida em um caractere de nova linha.Todos juntos, o argumento se torna
s / / \ newline/ g
[Foi divertido. Demorou um pouco para desembrulhar isso. +1 para uma pergunta interessante.]
fonte
A expressão
$'...'
é umbash
ismo que produz...
com as seqüências de escape padrão expandidas. º\'
antes que significa apenas uma barra invertida seguida pela final da seção citada, a cadeia resultante és/ /\
. (Sim, você pode alternar entre aspas no meio de uma sequência; ela não termina a sequência.)O padrão POSIX
sed
aceita apenas\n
como parte de um padrão de pesquisa. O OS X usa o FreeBSDsed
, que é estritamente compatível com POSIX; O GNU, como sempre, adiciona coisas extras e, em seguida, os usuários do Linux pensam que isso é algum tipo de "padrão" (talvez eu ficasse mais impressionado se algum deles tivesse um processo de padrões).fonte
$'...'
parte. Mas ... o que és/ /\
? Como assimswitch quoting
?'...'
é um tipo de citação de shell;$'...'
é outro. Há também"..."
e\x
para citar um único personagem. Você pode combinar aqueles em uma única palavra, que é o que estava sendo feito lá, alternando de uma''
string normal para uma$''
string para traduzir o\n
. Quanto ao resto, está construindo umsed
comando (s/text/replacement/flags
). Nesse caso, o comando é iniciado, incluindo uma barra invertida no final para proteger a nova linha literal$'\n/g'
anexada. O resultado é substituir todos os/g
espaços (o sinalizador) por novas linhas.É muito fácil ver visualmente o que está acontecendo. Simplesmente ecoar a corda!
resulta em
que é equivalente a
s/$/\
newline/g
Se você não tivesse o extra
\
antes donewline
, o shell interpretarianewline
o final do comando prematuramente.fonte