Como inserir uma barra invertida e uma nova linha antes de um padrão?

0

Eu queria capturar \ n em uma variável (assumir a) e substituir $ a na frente do padrão de pesquisa em um arquivo (abc.txt)

alguém pode me sugerir a solução?

> cat abc.txt
hi how are you how is your health
> echo $a
\

saída esperada (padrão de pesquisa - how )

hi \
how are you \
how is your health
    
por Vikas Venna 21.11.2017 / 14:43

2 respostas

1

Em um shell tipo Bourne ou rc

a='
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt

passaria uma variável de ambiente a para perl contendo um caractere de nova linha e perl inseriria o conteúdo dessa variável antes de cada ocorrência de pattern no conteúdo de abc.txt .

Para atribuir qualquer caractere x diferente de ' a uma variável em shells semelhantes a Bourne, você pode usar:

a='x'

Então, para a barra invertida:

a='\'

Para nova linha:

a='
'

Para caracteres de controle como newline, mas isso seria ainda pior para backspace ou carriage-return, por exemplo, que torna o código menos legível.

O ksh93 introduziu uma nova forma de aspas $'...' para especificar esses caracteres em um formulário com escape. Outros shells como bash , zsh , mksh ou FreeBSD sh copiaram e estenderam (como $'\uXXXX' forma adicionada por zsh ) desde então.

Nesses shells, você pode usar:

a=$'\n' a=$'\b' a=$'\r' a=$'\' a=$'\''

Para atribuir um caractere de nova linha, retrocesso, retorno de carro, barra invertida ou aspas simples.

Esse operador de cotação ainda não é padrão, por isso você não pode usá-lo em um script sh portátil. Uma alternativa padrão é usar:

a=$(printf '\b')

para backspace, por exemplo, mas isso não funciona para newline, pois a substituição de comando ( $(cmd) ) retira caracteres de nova linha da saída de cmd . É preciso recorrer a hacks como:

nl=$(printf '\n.'); nl=${nl%.}

(isto é, adicione um . e remova-o depois) para preservá-lo.

Observe que perl também entende essas notações de \n em seu código, então você pode fazer:

perl -pe 's/pattern/\n$&/g' < abc.txt

A implementação GNU de sed (e alguns outros atualmente) também suporta:

sed 's/pattern/\n&/g' < abc.txt

mas isso não é padrão. Normalmente, uma nova linha na parte de substituição do comando s em sed tem que ser expressa com uma barra invertida seguida por uma nova linha, de modo que seria:

backslash='\' newline='
'
sed "s/pattern/$backslash$newline&/g" < abc.txt

Ou sem as variáveis:

sed 's/pattern/\
&/g' < abc.txt

Portanto, se você quiser inserir uma barra invertida e uma nova linha na frente de pattern , será necessário:

sed 's/pattern/\\
&/g' < abc.txt

3 barras invertidas no total, duas para uma barra invertida literal e uma para a nova linha. Ou com perl :

perl -pe 's/pattern/\\n$&/g' < abc.txt

Ou com sua variável a :

a='\
' perl -pe 's/pattern/$ENV{a}$&/g' < abc.txt
    
por 21.11.2017 / 14:48
0

Você também pode usar os próprios comandos bash usando:

cat abc.txt | sed -e 's/how/\nhow/g' |  while read line; do echo "$line \"; done
    
por 21.11.2017 / 16:23