Como eu uso newlines dentro () com sed?

2

Quando eu quiser substituir, diga Dot com

Dot
##empty line##

Eu faço isso:

sed 's/Dot/Dot\
/g'

Sim, uma nova linha literal, é assim que funciona no BSD sed . Mas não consigo fazer o mesmo quando o sed está entre parênteses. Exemplo de comando:

lol=$(echo $varcontaining something | sed 's/Dot/Dot\
/g')

Porque ele só será substituído por . (espaço em branco)

    
por DisplayName 28.11.2014 / 17:05

4 respostas

1

O Shell remove as novas linhas finais. A solução alternativa comum é adicionar um caractere no final da substituição do comando e removê-lo.

x=$( echo a; echo ; echo :)
echo "${x%:}"
    
por 28.11.2014 / 17:19
1

E esses métodos mencionados neste Stackoverflow Q & A intitulado: Como faço para usar uma nova linha de reposição em um BSD sed? :

sed -e 's/ /\'$'\n/g'

Ou outro método mencionado onde você coloca a nova linha em uma variável da seguinte forma:

cr="
"

Em seguida, use a variável:

sed "s/ /\${cr}/g"
    
por 29.11.2014 / 02:13
1

Provavelmente, a maneira mais eficaz de fazer isso - como eu considero - é com eval . Se você quiser valores literais de uma expansão de shell, a maneira mais direta de obtê-los é a entrada literal - e a única maneira de obter isso da saída de um shell é alimentá-lo de volta.

Geralmente, é mais fácil trabalhar com ' aspas duras. A regra de cotação simples para uma ' com cotação incorreta ' é que ela não pode conter uma cotação difícil - a única maneira de obter uma interpretada em tal contexto é concatenar 2 ou mais cadeias entre aspas como ...

VAR='string'\''more string'

Dessa forma, a primeira string entre aspas termina na segunda aspa, a segunda string citada é apenas uma daspas duras com escape de barra invertida, e a terceira é a quarta aspa dura até o final.

E então o que eu poderia fazer se você fosse ...

eval "lol='$(nl='\
';    printf %s\n "$lol" |
      sed "s/Dot/&$nl/g
           s/'"'/&\&&/g
          $s/$/'"'/
")"

Dessa forma, a mesma linha inicial que printf adiciona ao valor do var é aquela que a substituição do comando retira - que também é o último caractere na saída porque o segundo ao último caractere é sempre uma citação difícil - e que delimita com segurança a instrução eval porque sed escapa de aspas duras que podem aparecer em sua entrada e há uma na parte superior da string.

Na verdade, usar substituições de comandos como essa não é uma boa prática de qualquer maneira - e talvez por isso não caiba bem o tempo todo. Geralmente, é mais eficiente reunir todas as saídas de um processo para cada um de seus loops de processo e transferi-las de uma só vez em um único fluxo para outro processo de filtro em um pipeline do que fazer um nick e dime dos filtros dessa maneira.

E, a menos que você tenha valores enormes em suas variáveis de shell - o que também costuma ser uma má ideia -, algo assim provavelmente é o melhor caminho a seguir:

set -- "$lol" 
while case "$1" in (*Dot*)
set -- "${1%Dot*}" "${1##*Dot}Dot
$2";;(*) ! lol=$1$2;; esac
do :; done
    
por 30.11.2014 / 13:44
0

Você pode usar a nova linha \n junto com o retorno de carro \r . Eu não tenho BSD sed para testar, mas funciona com o GNU sed .

$ var=Dot
$ lol=$(echo $var | sed 's/Dot/Dot\n\r/g')
$ echo "$lol"
Dot

$

Se o BSD sed não suportar \r , outra solução (bastante feia) será imprimir \n\r com echo -e ou printf :

lol=$(echo $var | sed "s/Dot/Dot\$(printf '\n\r')/g")
    
por 28.11.2014 / 17:46