linux - sed command a expects \ followed by text




Comando sed com opção-i falhando no Mac, mas funciona no Linux (8)

Eu usei com sucesso o seguinte comando sed para procurar / substituir texto no Linux:

sed -i 's/old_link/new_link/g' *

No entanto, quando eu tento no meu Mac OS X, recebo:

"comando c espera \ seguido por texto"

Eu pensei que meu Mac executa um shell BASH normal. Estás bem?

EDITAR:

De acordo com o @High Performance, isso deve-se ao facto de o Mac sed ter um sabor diferente (BSD), pelo que a minha pergunta seria, portanto, como replicar este comando no BSD sed ?

EDITAR:

Aqui está um exemplo real que faz isso:

sed -i 's/hello/gbye/g' *

A resposta de Sinetris está certa, mas eu uso isso com o comando find para ser mais específico sobre quais arquivos eu quero mudar. Em geral, isso deve funcionar (testado em osx /bin/bash ):

find . -name "*.smth" -exec sed -i '' 's/text1/text2/g' {} \;

Em geral, quando usar sed sem find em projetos complexos é menos eficiente.


Como as outras respostas indicam, não há uma maneira de usar o sed portável no OS X e no Linux sem fazer arquivos de backup. Então, eu usei este verso do Ruby para fazer isso:

ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml

No meu caso, eu precisava chamá-lo de uma tarefa rake (ou seja, dentro de um script Ruby), então usei este nível adicional de citação:

sh %q{ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml}

Eu criei uma função para lidar com a diferença de sed entre o MacOS (testado no MacOS 10.12) e outro sistema operacional:

OS=`uname`
# $(replace_in_file pattern file)
function replace_in_file() {
    if [ "$OS" = 'Darwin' ]; then
        # for MacOS
        sed -i '' -e "$1" "$2"
    else
        # for Linux and Windows
        sed -i'' -e "$1" "$2"
    fi
}

Uso:

$(replace_in_file 's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' "./mysql/.env")

Onde:

é um delimetro

's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' é padrão

"./mysql/.env" é o caminho para o arquivo


Isso funciona com as versões GNU e BSD do sed:

sed -i'' -e 's/old_link/new_link/g' *

ou com backup:

sed -i'.bak' -e 's/old_link/new_link/g' *

Observe a falta de espaço após a opção -i ! (Necessário para o GNU sed)


Se você usar a opção -i precisará fornecer uma extensão para seus backups.

Se você tem:

File1.txt
File2.cfg

O comando (note a falta de espaço entre -i e '' e -e para fazê-lo funcionar em novas versões do Mac e no GNU):

sed -i'.original' -e 's/old_link/new_link/g' *

Crie 2 arquivos de backup como:

File1.txt.original
File2.cfg.original

Não há nenhuma maneira portátil de evitar fazer arquivos de backup porque é impossível encontrar uma combinação de comandos sed que funcione em todos os casos:

  • sed -i -e ... - não funciona no OS X, pois cria backups -e
  • sed -i'' -e ... - não funciona no OS X 10.6, mas funciona em 10.9+
  • sed -i '' -e ... - não funciona no GNU

Nota Dado que não há um comando sed funcionando em todas as plataformas, você pode tentar usar outro comando para obter o mesmo resultado.

Por exemplo, perl -i -pe's/old_link/new_link/g' *


Seu Mac realmente roda um shell BASH, mas isso é mais uma questão de qual implementação do sed você está lidando. Em um Mac sed vem do BSD e é sutilmente diferente do sed que você pode encontrar em uma caixa típica do Linux. Eu sugiro que você man sed .


Veja como aplicar variáveis ​​de ambiente ao arquivo de modelo (sem necessidade de backup).

1. Crie um modelo com {{FOO}} para substituição posterior.

echo "Hello {{FOO}}" > foo.conf.tmpl

2. Substitua {{FOO}} com a variável FOO e imprima para o novo arquivo foo.conf

FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf

Trabalhando tanto o macOS 10.12.4 quanto o Ubuntu 14.04.5


sed -ie 's/old_link/new_link/g' *

Funciona tanto no BSD quanto no Linux







sed