Como usar o sed para escrever em um nome de arquivo armazenado em uma variável?

Como usar o sed para escrever em um nome de arquivo armazenado em uma variável?

De dentro de um bashscript, como posso sedescrever em um arquivo onde o nome do arquivo está armazenado em uma variável bash? O redirecionamento de saída não funciona porque quero editar um arquivo no local, puxando linhas que correspondem a um regex para um arquivo diferente e excluindo-as no primeiro arquivo.

Algo como:

sed -i '/^my regex here$/{;w file2;d;}' file1

...mas onde file1e file2estão ambos na verdadevariáveisqueseguraros nomes dos arquivos. (Como file2=$(mktemp).)

Então, o que eu realmente quero é a expansão variável para o nome do arquivo, mas nenhuma expansão para o resto do sedcomando, e deixar tudo como um único argumento passado para o sedcomando.

Por alguma razão, o seguinte não funciona:

sed -i '/my regex here/{;w '"$file2"';d;}' $file1

Diz "incomparável {" e não consigo entender por quê.

De alguma forma eu posso fazer isso?

Responder1

Como você está usando uma única sedexpressão, tudo o que vem depois do w(incluindo o }) éinterpretado como oarquivo wnome:

O argumento wfileencerrará o comando de edição.

Você pode ver isso se adicionar um segundo comando, }por exemplo:

sed -e '/my regex here/{w '"$file2"';d;}' -e '}' $file1

então as linhas correspondentes my regex hereserão salvas em um arquivo chamado whatever;d;}onde whateverestá o que for $file1expandido.
A sintaxe correta é através de comandos separados, seja com diversas expressões:

sed -e '/my regex here/{w '"$file1" -e 'd' -e '}' $file2

ou um comando por linha:

sed '/my regex here/{
w '"$file1"'
d
}
' $file2

Responder2

encontrei a resposta emStackoverflowem "Como faço para que o comando sed 'w' saiba onde termina o nome do arquivo?"

Como Terdon apontou, a questão não é a variável – mas também não tem nada a ver com chaves; tente sed '/^l/w testing;p'e você verá que não gera nenhum erro, mas grava todas as linhas começando com a lem um arquivo chamado testing;p.

O problema é, na verdade, a falta de uma nova linha após o nome do arquivo.

Portanto, a resposta é usar uma nova linha embutida no comando sed:

sed -i '/my regex here/{;w '"$file2"'
d;}' $file1

Ou, o que é muito mais limpo, use dois -eargumentos separados:

sed -i -e '/my regex here/{;w '"$file2" -e 'd;}' $file1

Se você não gostar das duas aspas adjacentes (que você pode facilmente escorregar), basta colocar o comando write em seu próprio argumento:

sed -i -e '/^my regex here$/{' -e "w $file2" -e 'd;}' $file1

Responder3

Use aspas duplas em vez das simples para citar o comando sed. E não se esqueça de escapar dos personagens adequados.

Mais informações sobre como citar variáveis ​​no bash nestelink

informação relacionada