Existe uma chamada sed
para edição in-loco de tarefas sem backups que funciona tanto no Linux quanto no Mac? Embora o BSD sed
enviado com o OS X pareça necessário sed -i '' …
, as sed
distribuições GNU Linux geralmente vêm com interpretam as aspas como um nome de arquivo de entrada vazio (em vez da extensão de backup) e precisam sed -i …
.
Existe alguma sintaxe da linha de comando que funcione com os dois tipos, para que eu possa usar o mesmo script nos dois sistemas?
Respostas:
Se você realmente deseja apenas usar
sed -i
a maneira 'fácil', o seguinte funciona no GNU e no BSD / Macsed
:Observe a falta de espaço e o ponto.
Prova:
Obviamente, você pode excluir os
.bak
arquivos.fonte
sed
)sed
não aceita umcommand
argumento posicional quando invocado com-i
- ele deve ser fornecido com outro sinalizador-e
,. Assim, o comando se torna:sed -i.bak -e 's/foo/bar/' filename
sed -i.bak 's/foo/bar/' file && rm file.bak
Isso funciona com o GNU sed, mas não no OS X:
Isso funciona no OS X, mas não no GNU sed:
No OS X você
sed -i -e
pois a extensão do arquivo de backup seria definida como-e
sed -i'' -e
pelos mesmos motivos - ele precisa de um espaço entre-i
e''
.fonte
-i
e-i''
são idênticos no momento da análise de shell;sed
não pode se comportar de maneira diferente nessas duas primeiras invocações, porque obtém exatamente os mesmos argumentos.Quando no OSX, eu sempre instalo a versão GNU sed via Homebrew, para evitar problemas nos scripts, porque a maioria dos scripts foi escrita para as versões GNU sed.
Então o seu BSD sed será substituído pelo GNU sed.
Como alternativa, você pode instalar sem nomes padrão, mas depois:
PATH
conforme as instruções após a instalaçãognu-sed
gsed
oused
dependendo do seu sistemafonte
--with-default-names
foi removido do homebrew-core , mais informações em esta resposta. ao instalargnu-sed
agora, as instruções de instalação especificam que você precisa adicionargnubin
ao seuPATH
:PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Como Noufal Ibrahim pergunta, por que você não pode usar Perl? Qualquer Mac terá Perl, e há muito poucas distribuições Linux ou BSD que não incluem alguma versão do Perl no sistema básico. Um dos únicos ambientes que podem realmente não ter o Perl seria o BusyBox (que funciona como o GNU / Linux para
-i
, exceto que nenhuma extensão de backup pode ser especificada).Como o ismail recomenda,
e isso parece ser uma solução melhor em quase todos os casos do que scripts, aliases ou outras soluções alternativas para lidar com a incompatibilidade fundamental
sed -i
entre o GNU / Linux e o BSD / Mac.fonte
perl
faz parte da especificação Linux Standard Base desde 1 de maio de 2009. refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Languages/…Não há como fazê-lo funcionar.
Uma maneira é usar um arquivo temporário como:
Isso funciona em ambos
fonte
Resposta: Não.
A resposta originalmente aceita, na verdade, não faz o que é solicitado (conforme observado nos comentários). (Encontrei esta resposta ao procurar o motivo pelo qual um
file-e
estava aparecendo "aleatoriamente" nos meus diretórios.)Aparentemente, não há como começar
sed -i
a trabalhar consistentemente no MacOS e no Linuces.Minha recomendação, para o que vale a pena, não é atualizar no local
sed
(que possui modos de falha complexos), mas gerar novos arquivos e renomeá-los posteriormente. Em outras palavras: evite-i
.fonte
A
-i
opção não faz parte do POSIX Sed . Um método mais portátil seria usar o Vim no modo Ex:%
selecione todas as linhass
substituirx
salvar e fecharfonte
Aqui está outra versão que funciona no Linux e no macOS sem usar
eval
e sem precisar excluir arquivos de backup. Ele usa matrizes Bash para armazenar ossed
parâmetros, o que é mais limpo do que usareval
:Isso não cria um arquivo de backup, nem um arquivo com aspas anexadas.
fonte
sedi=(-i) && [ "$(uname)" == "Darwin" ] && sedi=(-i '')
sed "${sedi[@]}" -e 's/foo/bar/' target.file
Resposta de Steve Powell é bastante correta, consultando a página MAN para sed no OSX e Linux (Ubuntu 12.04) destaca a compatibilidade dentro do uso sed 'in-loco' nos dois sistemas operacionais.
JFYI, não deve haver espaço entre o -i e as aspas (que denotam uma extensão de arquivo vazia) usando a versão Linux do sed, portanto
Página do Man Linux
e
Página de manual OSX sed
Eu contornei isso em um script usando um comando alias'd e a saída do nome do SO ' uname ' dentro de um bash 'if'. A tentativa de armazenar cadeias de comando dependentes do SO em variáveis foi um acerto e um erro ao interpretar as aspas. O uso de ' shopt -s expand_aliases ' é necessário para expandir / usar os aliases definidos em seu script. O uso de shopt é tratado aqui .
fonte
Se você precisar executar o script
sed
em um localbash
e NÃO desejar que o resultado seja gerado com arquivos .bkp, e você tenha uma maneira de detectar o sistema operacional (por exemplo, usando ostype.sh ), - O seguinte hack com obash
shell internoeval
deve funcionar:fonte
Você pode usar esponja. O Sponge é um antigo programa unix, encontrado no pacote moreutils (tanto no ubuntu quanto provavelmente no debian, e no homebrew no mac).
Ele armazena em buffer todo o conteúdo do canal, aguarde até que o canal esteja fechado (provavelmente significa que o arquivo de entrada já está fechado) e substituirá:
Na página do manual :
fonte
O seguinte funciona para mim no Linux e OS X:
sed -i' ' <expr> <file>
por exemplo, para um arquivo que
f
contémaaabbaaba
sed -i' ' 's/b/c/g' f
produz
aaaccaaca
em Linux e Mac. Observe que há uma string entre aspas que contém um espaço , sem espaço entre-i
a string e a string. Aspas simples ou duplas funcionam.No Linux, estou usando a
bash
versão 4.3.11 no Ubuntu 14.04.4 e no Mac versão 3.2.57 no OS X 10.11.4 El Capitan (Darwin 15.4.0).fonte
Eu encontrei esse problema. A única solução rápida foi substituir o sed in mac pela versão gnu:
fonte