Substitua as correspondências pela string multilinha usando sed [duplicate]

3

Eu tenho um arquivo chamado foo.txt contendo:

foo
bar
baz

Eu quero substituir todas as ocorrências de bar por uma string multilinha, armazenada na variável $bar :

1
2
3

Como resultado:

foo
1
2
3
baz

Eu posso fazer isso em awk usando:

echo "$bar" | awk '{
        if(FILENAME == "-")
        {
            if(i != "")
            {
                i = i"\n"
            }
            i = i$0
        }
        else
        {
            if($0 == "bar")
            {
                printf i
            }
            else
            {
                print
            }
        }
    }'

No entanto, tentar fazer o mesmo em sed usando sed 's/bar/'"$bar"'/' foobar.txt fornece o erro:

sed: 1: "s/bar/1
2
3/": unescaped newline inside substitute pattern

Isso pode ser corrigido?

Se houver uma maneira ainda mais fácil de fazer isso usando outra ferramenta padrão, eu gostaria de saber isso também.

    
por Tyilo 04.01.2013 / 20:50

2 respostas

5

Em sed , um caractere de nova linha precisa ser escapado no lado direito do comando s , então você precisa escrevê-lo:

sed 's/foo/1\
2\
3/g'

Algumas implementações sed também suportam o (não padrão):

sed 's/foo/1\n2\n3/g'

Se $bar for a substituição, você precisará primeiro inserir uma barra invertida antes de cada caractere de nova linha. Enquanto você está nisso, você também deve inserir uma barra invertida antes de cada barra, barra invertida e caractere de e comercial.

Algo como:

bar_escaped=$(printf '%s\n' "$bar" | sed 's,[\/&],\&,g;s/$/\/')
bar_escaped=${bar_escaped%?}
sed "s/foo/$bar_escaped/g"
    
por 04.01.2013 / 21:26
1

O que fiz foi criar um arquivo sed pattern e, em seguida, chamar sed com esse arquivo especificado em vez de especificar o padrão dentro do comando porque você não pode fazer várias linhas na linha de comando (isto é, não é legal). Por exemplo,

sed -f pattern_file.sed infile.txt

No meu caso, eu queria encontrar todas as linhas que leiam alarm_if_fail: 1 e adicionar application: XYZ na linha seguinte. Então pattern_file.sed é o seguinte:

1,/^END/{


        s/^alarm_if_fail: 1$/&\
application: XYZ/


}

Se infile.txt se parece com

Unix
Stackexchange

alarm_if_fail: 1

ABC

Em seguida, ed -f pattern_file.sed infile.txt retornará

Unix
Stackexchange

alarm_if_fail: 1
application: XYZ

ABC
    
por 04.01.2013 / 21:10

Tags