comando - sinalizador sed in-place que funciona tanto no Mac(BSD) quanto no Linux




sed mac file (9)

A opção -i não faz parte do POSIX Sed . Um método mais portátil seria usar o Vim no modo Ex:

ex -sc '%s/alfa/bravo/|x' file
  1. % selecione todas as linhas

  2. s substituir

  3. x salvar e fechar

Existe uma invocação da edição local no local sem backups que funcionem tanto no Linux quanto no Mac? Embora o BSD sed fornecido com o OS X pareça precisar de sed -i '' … , as distribuições Linux GNU sed geralmente vêm com interpreta as aspas como nome de arquivo de entrada vazio (em vez da extensão de backup) e precisa de sed -i … .

Existe alguma sintaxe de linha de comando que funciona com ambos os tipos, para que eu possa usar o mesmo script em ambos os sistemas?


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 os parâmetros sed , que é mais limpo do que usando eval :

# Default case for Linux sed, just use "-i"
sedi=(-i)
case "$(uname)" in
  # For macOS, use two parameters
  Darwin*) sedi=(-i "")
esac

# Expand the parameters in the actual call to "sed"
sed "${sedi[@]}" -e 's/foo/bar/' target.file

Isso não cria um arquivo de backup nem um arquivo com aspas anexadas.


Eu me deparei com esse problema. A única solução rápida foi substituir o sed no mac pela versão do gnu:

brew install gnu-sed

Isso funciona com o GNU sed, mas não no OS X:

sed -i -e 's/foo/bar/' target.file
sed -i'' -e 's/foo/bar/' target.file

Isso funciona no OS X, mas não no GNU sed:

sed -i '' -e 's/foo/bar/' target.file

No OS X você

  • Não é possível usar sed -i -e pois a extensão do arquivo de backup seria definida como -e
  • não pode usar sed -i'' -e pelas mesmas razões - ele precisa de um espaço entre -i e '' .

O seguinte funciona para mim no Linux e no OS X:

sed -i' ' <expr> <file>

por exemplo, para um arquivo contendo aaabbaaba

sed -i' ' 's/b/c/g' f

produz aaaccaaca no Linux e no Mac. Note que há uma string entre aspas que contém um espaço , sem espaço entre o -i e a string. Aspas simples ou duplas funcionam.

No Linux eu estou usando o 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).


Quando no OSX, eu sempre instalo a versão GNU sed via Homebrew, para evitar problemas nos scripts, porque a maioria dos scripts foram escritos para versões do GNU sed.

brew install gnu-sed --with-default-names

Então o seu BSD sed será substituído pelo GNU sed.

Como alternativa, você pode instalar sem nomes padrão, mas:

  • Altere seu PATH conforme instruído após instalar o gnu-sed
  • Verifique seus scripts para escolher entre gsed ou sed dependendo do seu sistema

Se você realmente quer apenas usar o sed -i da maneira 'fácil', o seguinte funciona tanto no GNU quanto no BSD / Mac sed :

sed -i.bak 's/foo/bar/' filename

Observe a falta de espaço e o ponto.

Prova:

# GNU sed
% sed --version | head -1
GNU sed version 4.2.1
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

# BSD sed
% sed --version 2>&1 | head -1
sed: illegal option -- -
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

Obviamente, você poderia simplesmente excluir os arquivos .bak .


Você pode usar esponja. O Sponge é um antigo programa unix, encontrado no pacote moreutils (tanto no Ubuntu quanto no Debian, e no Homebrew no Mac).

Ele armazenará em buffer todo o conteúdo do pipe, aguardará até que o canal esteja próximo (provavelmente o arquivo de entrada já estará próximo) e, em seguida, sobrescreverá:

Na página man :

Sinopse

sed '...' file | grep '...' | arquivo de esponja


A resposta de Steve Powell é bastante correta, consultando a página MAN para sed no OSX e o Linux (Ubuntu 12.04) destaca a compatibilidade dentro do uso de sed no local entre os dois sistemas operacionais.

JFYI, não deve haver espaço entre o -i e quaisquer citações (que indicam uma extensão de arquivo vazia) usando a versão do Linux do sed,

sed Linux Man Page

#Linux
sed -i"" 

e

sed Homem Página OSX

#OSX (notice the space after the '-i' argument)
sed -i "" 

Eu peguei isso em um script usando um comando alias'd e a saída do nome OS do ' uname ' dentro de um bash 'if'. Tentando armazenar seqüências de comandos dependentes do sistema operacional em variáveis ​​foi acertar e errar ao interpretar as aspas. O uso de ' shopt -s expand_aliases ' é necessário para expandir / usar os aliases definidos dentro do seu script. O uso de shopt é tratado here .





bsd