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

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

eu queria capturar \n em uma variável (suponha 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

Responder1

Em um shell tipo Bourne ou tipo rc

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

passaria uma avariável de ambiente perlcontendo um caractere de nova linha e perlinseriria o conteúdo dessa variável antes de cada ocorrência de patternno conteúdo de abc.txt.

Para atribuir qualquer caractere xque não seja 'uma variável em shells do tipo Bourne, você pode usar:

a='x'

Então, para barra invertida:

a='\'

Para nova linha:

a='
'

Para caracteres de controle como nova linha, mas isso seria ainda pior para backspace ou retorno de carro, por exemplo, que torna o código menos legível.

ksh93 introduziu uma nova $'...'forma de aspas para especificar esses caracteres em formato de escape. Outros shells como bash, zshou mkshFreeBSD sho copiaram e estenderam (como o $'\uXXXX'formulário adicionado por zsh) desde então.

Nessas conchas, 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, portanto você não pode usá-lo em um shscript portátil. Uma alternativa padrão é usar:

a=$(printf '\b')

para backspace, por exemplo, mas isso não funciona para nova linha, pois a substituição de comando ( $(cmd)) remove os caracteres de nova linha à direita 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 perltambém entende essas \nnotações em seu código, então você pode fazer:

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

A implementação GNU sed(e algumas outras hoje em dia) 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 scomando in seddeve 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

Então, se quiser inserir uma barra invertida e uma nova linha na frente de pattern, você precisa:

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 avariável:

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

Responder2

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

informação relacionada