Edições no local com sed no OS X


142

Gostaria de editar um arquivo com o sed no OS X. Estou usando o seguinte comando:

sed 's/oldword/newword/' file.txt

A saída é enviada para o terminal. file.txt não foi modificado. As alterações são salvas no arquivo2.txt com este comando:

sed 's/oldword/newword/' file1.txt > file2.txt

No entanto, eu não quero outro arquivo. Eu só quero editar file1.txt . Como posso fazer isso?

Eu tentei a bandeira -i. Isso resulta no seguinte erro:

sed: 1: "file1.txt": invalid command code f

2
Qual é o comando exato que você está usando quando tenta a -ibandeira?
Eldarerathis

Respostas:


282

Você pode usar o -isinalizador corretamente fornecendo um sufixo para adicionar ao arquivo de backup. Estendendo seu exemplo:

sed -i.bu 's/oldword/newword/' file1.txt

Você fornecerá dois arquivos: um com o nome file1.txtque contém a substituição e outro com o nome file1.txt.buque possui o conteúdo original.

Ligeiramente perigoso

Se você deseja sobrescrever destrutivamente o arquivo original, use algo como:

sed -i '' 's/oldword/newword/' file1.txt
      ^ note the space

Devido à maneira como a linha é analisada, é necessário um espaço entre o sinalizador de opção e seu argumento, porque o argumento é de comprimento zero.

Além de possivelmente destruir o original, não conheço outros perigos de enganar dessa maneira. Deve-se notar, no entanto, que se essa invocação fizer sedparte de um script, o The Unix Way ™ (IMHO) deve ser usado de maneira sednão destrutiva, testando se saiu corretamente e somente depois removendo o arquivo estranho.


Você está certo, eu estava omitindo a extensão depois da bandeira -i. É -i''perigoso por qualquer motivo, além de potencialmente atrapalhar o arquivo original (e não ter backup)?
Segunda

De acordo com a sedpágina do manual, se você ficar sem espaço em disco no dispositivo, poderá corromper um arquivo no meio do caminho e ter um resultado de saída ruim. Se você estiver trabalhando sob o controle de origem local sed -i ""sem backups, deverá ficar bem a maior parte do tempo (ou imediatamente git init && git add -A . && git commit -m 'backup'antes de executar o -imodo sed ).
cfeduke 29/05

2
Achei o pouco levemente perigoso particularmente útil. +1
Andre

5
O BSD sed requer que não haja espaço após o sinalizador -i. Então, -i''é válido, mas -i ''não é.
Todd A. Jacobs

3
Argh! O BSD sed está ignorando o caractere '\ n' e imprimindo 'n'! Só vou substituir o BSD sed pelo GNU sed no meu mac!
Nterry 11/03/16

20

Eu tenho problema semelhante com o MacOS

sed -i '' 's/oldword/newword/' file1.txt

não funciona, mas

sed -i"any_symbol" 's/oldword/newword/' file1.txt

funciona bem.


Agora é o contrário. sed -i '' <file>funciona mas sed -i'' <file>não funciona mais
Zohaib Amanzai


4

Você pode usar -i''( --in-place) sedcomo já sugerido. Veja: O -iargumento in-loco , no entanto, observe que a -iopção é extensões não-padrão do FreeBSD e pode não estar disponível em outros sistemas operacionais. Em segundo lugar, sedé um editor ED do S tream , não um editor de arquivos .


Uma maneira alternativa é usar a substituição embutida no modo Vim Ex, como:

$ ex +%s/foo/bar/g -scwq file.txt

e para vários arquivos:

$ ex +'bufdo!%s/foo/bar/g' -scxa *.*

Para editar todos os arquivos recursivamente, você pode usar **/*.*se o shell suportar isso (ativar por shopt -s globstar).


Outra maneira é usar gawke sua nova extensão "local" , como:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1

4

Isso cria arquivos de backup. Por exemplo, sed -i -e 's/hello/hello world/' testfilepara mim, cria um arquivo de backup, testfile-e, no mesmo diretório.


O mesmo aqui com o Mac OS Catalina. Passar -i e -e separadamente (NÃO -e juntos!) Cria um arquivo de backup com '-e' anexado.
Daniel Kesner 20/04

1

Você pode usar:

sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>

Exemplo:

sed -i -e 's/Hello/Bye/' file.txt

Isso funciona perfeitamente no Mac .


2
Isso cria um arquivo de backup para mim no Mac OS Catalina com '-e' anexado.
Daniel Kesner 20/04

Isso está errado no macOS. Por favor, dê uma olhada na página "man sed" lá. -irequer um argumento para o macOS. Como você não especifica um, ele usa -e, o que resulta em ter um segundo arquivo -eanexado. -enão existe no macOS, é -E. O comando tão correto para o macOS ésed -i '' -E 's/Hello/Bye/' file.txt
Marc J. Schmidt
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.