De dentro de um bash
script, como posso sed
escrever 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 file1
e file2
estã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 sed
comando, e deixar tudo como um único argumento passado para o sed
comando.
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 sed
expressão, tudo o que vem depois do w
(incluindo o }
) éinterpretado como oarquivo wnome:
O argumento
wfile
encerrará 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 here
serão salvas em um arquivo chamado whatever;d;}
onde whatever
está o que for $file1
expandido.
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 l
em 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 -e
argumentos 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