Gostaria de editar um arquivo no local anexando uma linha, apenas se ainda não existir, para tornar meu script à prova de balas.
Normalmente eu faria algo como:
cat >> ~/.bashrc <<EOF
export PATH=~/.composer/vendor/bin:\$PATH
EOF
Também é possível fazer isso via ansible ( line
+ insertafter=EOF
+ regexp
), mas é outra história.
No vi / ex, eu poderia fazer algo como:
ex +'$s@$@\rexport PATH=\~/.composer/vendor/bin:$PATH@' -cwq ~/.bashrc
mas como verificar se a linha já está lá (e, portanto, não faço nada) idealmente sem repetir a mesma linha?
Ou talvez haja alguma maneira mais fácil de fazer isso no editor Ex?
substitute
ex-command
kenorb
fonte
fonte
grep -Fq 'export PATH=~/.composer/vendor/bin:$PATH' ~/.bashrc || ex ...
(oucat
, nesse caso)?ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"
export
é um comando , portanto, o restante da linha é uma palavra shell, NÃO uma atribuição. Portanto, diferentemente de uma atribuição de variável (que não usaexport
), você precisa de aspas duplas ou ela será quebrada no espaço em branco . Consulte também Como adicionar corretamente um caminho ao PATH .Respostas:
Se você quiser ser à prova de balas , provavelmente desejará algo um pouco mais portátil do que as opções complicadas acima. Gostaria de manter os recursos do POSIX
ex
e torná-lo estúpido-simples: basta remover a linha se ela estiver lá (independentemente de quantas vezes estiver lá), adicione-a ao final do arquivo e salve e saia:Eu ancorei o regex para maior robustez, apesar de achar quase impossível coincidir acidentalmente com esse regex. (Ancorado significa usar
^
e,$
portanto, a regex corresponderá apenas se corresponder a uma linha inteira .)Observe que a
+cmd
sintaxe não é requerida pelo POSIX, nem o recurso comum de permitir vários-c
argumentos.Existem várias outras maneiras simples de fazer isso. Por exemplo, adicione a linha ao final do arquivo e execute as duas últimas linhas do arquivo através do filtro UNIX externo
uniq
:Isso é muito, muito limpo e simples, e também é totalmente compatível com POSIX. Ele usa o recurso Escape
ex
para filtragem de texto externa e o utilitário de shell especificado pelo POSIXuniq
A linha inferior é,
ex
foi projetada para edição de arquivos no local e é de longe a maneira mais portátil de fazer isso de maneira não interativa. Ele antecede até mesmo o originalvi
, na verdade, o nomevi
é para "editor visual", eo editor não-visual que foi construído em cima eraex
.)Para uma simplicidade ainda maior (e para reduzi-la a uma única linha), use
printf
para enviar os comandos paraex
:fonte
Uma solução possível é criar uma função para fazer isso:
Primeiro, criamos uma variável local
l:res
que será usada para contar o número de ocorrências da linha.Usamos o
global
comando: cada vez que a linha é correspondida,l:res
é incrementada.Finalmente, se
l:res
ainda é 0, significa que a linha não aparece no arquivo, então vamos para a última linha graças aG
, e criamos uma nova linhao
na qual escrevemos a linha a ser adicionada.Nota 1 O método usado para definir o valor de
l:res
é um pouco pesado e pode ser substituído pelo sugerido por @Alex em sua resposta com algo como:Nota 2 Também para tornar a função mais flexível, você pode usar argumentos:
escape()
para adicionar um\
na frente dos caracteres, o que pode causar um problema na pesquisa.Observe também que você ainda terá que escapar
\
sozinho ao chamar a função (não consegui escapar\
automaticamente):fonte
Experimentar:
Observe que
:append
não funcionará dentro doif endif
bloco com o modo Ex (consulte VimDoc ), então eu tenho que colocar donorm A...
lado de fora.fonte
Eu normalmente uso:
fonte
Para simplificar e evitar a presença de muitos
\
, a linha a ser adicionada seráexport PATH=mybin:PATH
.Estratégia principal: substitua o
mybin
texto " não " (todos os arquivos) por texto + definição de caminho-mybin:ou com mais indentação didática :
Se tivermos uma correspondência:
&
tem o texto completo debashrc
e&
não contém/mybin:/
então:
ATUALIZAÇÃO : Finalmente, podemos criar um script vim:
chmod 755 e instale-o. Uso:
bashrcfix
tenha cuidado: no
\v
modo,=
significa opcionalfonte
A maioria dessas respostas parece complicada e os bons e antigos comandos do shell:
Essa poderia ser facilmente uma função do Bash:
EDIT : O código de saída do grep é importante e, neste caso, precisa ser revertido
! grep
;grep -v
não sairá conforme o esperado nesta situação. Obrigado @joeytwiddle pela dica.fonte
grep -v
dá o código de saída que você deseja. Mas! grep
deveria fazê-lo.-v
just the!
.-F
para quegrep
não interprete caracteres como expressões regulares e 2. Use em-q
vez de redirecionar para/dev/null
. Veja meu comentário anterior sobre a questão .-q
e-F
opções? Eu pensei que o>/dev/null
era mais universal entre diferentes plataformas (sol vs hp vs Mac OS X vs Ubuntu vs FreeBSD vs ...)