Estou tentando alterar uma única palavra em uma linha específica de um arquivo, mas estou tendo problemas para conectar todos juntos.
Basicamente, em uma linha do meu arquivo existe a palavra-chave 'firmware_revision' e nesta linha (e somente nesta linha) quero substituir a palavra 'teste' pela palavra 'produção'.
Então eu posso fazer isso:
grep 'firmware_revision' myfile.py | sed 's/test/production'
Isso selecionará a linha que eu quero e executarei a substituição, mas não consigo descobrir como colocar essa nova linha no arquivo original para substituir a linha antiga. Obviamente, não posso apenas redirecioná-lo de volta para o arquivo, então o que devo fazer?
Mesmo se eu usar temporários, usando grep
para obter apenas a linha necessária, perco todos os outros dados no arquivo, para que eu não possa mais apenas redirecioná-los para um arquivo temporário e substituir o original pela temp.
Editar - Alguém pediu mais informações
Digamos que eu tenho um arquivo cheio de linhas como esta
[
('key_name1', str, 'value1', 'Description'),
('key_name2', str, 'value2', 'Description'),
('key_name3', str, 'value3', 'Description'),
('firmware_revision', str, 'my-firmware-name-test', 'Firmware revision name')
]
Agora, quero escrever um script (de preferência uma linha) que encontre a linha que contém 'firmware_revision' e altere todas as instâncias da palavra 'test' nessa linha para 'produção'. A palavra 'teste' pode estar em outros lugares nesse arquivo e eu não quero que elas sejam alteradas. Portanto, para deixar claro, quero alterar a linha acima para
('firmware_revision', str, 'my-firmware-name-production', 'Firmware revision name')
Como eu faço isso?
fonte
sed
é muito poderoso, ele pode executar ambas as funções (grep
e substituição), mas precisaremos de mais informações sobre a aparência da linha para ajudá-lo.sed -i.bak '/firmware_revision/ s/test/production/' myfile.py
Respostas:
Tentar:
Aqui,
/firmware_revision/
atua como uma condição. É verdade para linhas que correspondem à regexfirmware_revision
e false para outras linhas. Se a condição for verdadeira, o comando a seguir é executado. Nesse caso, esse comando é um comando substituto que substitui a primeira ocorrência detest
withproduction
.Em outras palavras, o comando
s/test/production/
é executado apenas nas linhas que correspondem ao regexfirmware_revision
. Todas as outras linhas passam inalteradas.Por padrão, o sed envia sua saída para a saída padrão. Você, no entanto, queria alterar o arquivo no local. Então, nós adicionamos a
-i
opção. Em particular,-i.bak
faz com que o arquivo seja alterado no lugar com uma cópia de backup salva com uma.bak
extensão.Se você decidiu que o comando funciona para você e deseja viver perigosamente e não criar um backup, com o GNU sed (Linux), use:
Por outro lado, no BSD (OSX), a
-i
opção deve ter um argumento. Se você não deseja manter um backup, forneça um argumento vazio. Assim, use:Editar
Na edição da pergunta, o OP solicita que todas as ocorrências
test
na linha sejam substituídas porproduction
. Nesse caso, adicionamos ag
opção ao comando substitute para uma substituição global (para essa linha):fonte
-i.bak
parte.-i
adicionado.sed
pode fazer ...''
depois-i
?sed -i '/firmware_revision/ s/test/production/g' myfile.py
contrário, apenas a primeira instância será alterada.Em máquinas mais antigas com old-school
sed
que não oferece suporte à opção-i
:fonte
ed
e fazê-lo em uma linha:printf %s\\n g/firmware_revision/s/test/production/g w q | ed -s myfile.py
ed(1)
não oferece nenhum pretexto para mostrar o uso demktemp(1)
.ed
faz. Em vez demv -f "$TF" myfile.pl
, usecat "$TF" > myfile.pl && rm -f "$TF"
. BTW, é uma boa prática usar nomes de variáveis em minúsculas (em$tf
vez de$TF
), eles garantem que não entrem em conflito com nenhum vars incorporado do bash (provavelmente outras conchas de bourne também).cat "$TF" > myfile.pl
tente o seguinte:touch a b; chmod 0444 a; cat b >a
(BTW,sed -i
também não funcionará nesse caso). Melhor deixar o usuário lidar com isso. Re::rm -f "$TF"
não é necessário, vejatrap ... EXIT
. Re: em$tf
vez de$TF
: talvez; é uma questão de estilo.umask
diferir das permissões originais. Quanto aos Vars maiúsculos, não é apenas uma questão de estilo - muitas pessoas que cometeram o erro de usar PATH ou RANDOM ou SHELL maiúsculas ou o que quer que seja para suas próprias variáveis descobriram da maneira mais difícil. (e sim, eu mesmo uso varios maiúsculos. Sei que está errado, estou tentando quebrar o hábito).