Usando sede nãovisívelArquivo temporário:

Usando sede nãovisívelArquivo temporário:

Tenho um requisito em meu projeto para substituir algum texto existente em um arquivo comofoocom algum outro texto comofooofoo:

abc.txt
name
foo
foo1

Então eu tentei:

sed -i "s/foo/fooofoo/g" abc.txt

No entanto, recebo este erro:

sed: opção ilegal --i

Encontrei no manual que devo usar:

sed -i\ "s/foo/fooofoo/g" abc.txt

No entanto, isso também não está funcionando.

Encontrei alternativas em perle awktambém, mas uma solução no Solaris sedseria muito apreciada.

Estou usando esta versão do bash:

GNU bash, versão 3.2.57(1)-lançamento (sparc-sun-solaris2.10)

Responder1

Usared. Está disponível na maioria das plataformas e pode editar seus arquivos no local.
Como sedse baseia na edsintaxe para substituição de padrões é semelhante:

ed -s infile <<\IN
,s/old/new/g
w
q
IN

Responder2

Se você não conseguir instalar o GNU sed, use:

sed "s/foo/fooofoo/g" abc.txt >abc.tmp && mv abc.tmp abc.txt

Isso usaredirecionamentopara enviar a saída do sed para um arquivo temporário. Se o sed for concluído com êxito, ele será substituído abc.txtpelo arquivo temporário.

Como pode ser visto no código fonte do GNU sed, é exatamente isso que sed -iacontece. Então, isso é tão eficiente quanto sed -i.

Se já existir uma chance abc.tmp, você pode querer usar mktempou um utilitário semelhante para gerar o nome exclusivo para o temporário.

Responder3

Se você quiser o equivalente a sed -i.bak, é bem simples.

Considere este script para GNU sed:

#!/bin/sh

# Create an input file to demonstrate
trap 'rm -r "$dir"' EXIT
dir=$(mktemp -d)
grep -v '[[:upper:][:punct:]]' /usr/share/dict/words | head >"$dir/foo"

# sed program - removes 'aardvark' and 'aardvarks'
script='/aard/d'

##########
# What we want to do
sed -i.bak -e "$script" "$dir"
##########

# Prove that it worked
ls "$dir"
cat "$dir/foo"

Podemos simplesmente substituir a linha marcada por

cp "$dir/foo" "$dir/foo.bak" && sed -e "$script" "$dir/foo.bak" >"$dir/foo"

Isso move o arquivo existente para um backup e grava um novo arquivo.

Se quisermos o equivalente a

sed -i -e "$script" "$dir"  # no backup

então é um pouco mais complexo. Podemos abrir o arquivo para leitura como entrada padrão e desvinculá-lo antes de direcionar a saída do sed para substituí-lo:

( cp "$dir/foo" "$dir/foo.bak"; exec <"$dir/foo.bak"; rm "$dir/foo.bak"; exec sed -e "$script" >"$dir/foo" )

Fazemos isso em um sub-shell, para que nosso stdin original ainda esteja disponível depois disso. É possível alternar entradas e voltar sem um subshell, mas dessa forma parece mais claro para mim.

Observe que temos o cuidado de copiar primeiro, em vez de criar um novo fooarquivo - isso é importante se o arquivo for conhecido por mais de um nome (ou seja, tiver links físicos) e você quiser ter certeza de não quebrar os links .

Responder4

Usando sede nãovisívelArquivo temporário:

Você pode evitar criar um separadovisível"arquivo temporário":

exec 3<abc.txt
rm abc.txt
sed 's/foo/fooofoo/' <&3 >abc.txt
exec 3<&-

Explicação

Os sistemas do tipo Unix não removem o conteúdo do arquivo do disco até que ele sejaambosdesvinculado no sistema de arquivos,enão aberto em nenhum processo. Portanto, você pode exec 3<abrir o arquivo no shell para leitura no descritor de arquivo 3, rmo arquivo (que o desvincula do sistema de arquivos) e, em seguida, chamar sedcom o descritor de arquivo 3 usado como entrada.

Observe que isso émuitodiferente disso:

# Does not work.
sed 's/foo/fooofoo/' <abc.txt >abc.txt

A diferença é que quando você faz isso em um comando, o shell apenas abre o mesmo arquivo tanto para leitura quanto para escrita com a opção de truncar o arquivo - como ainda é o mesmo arquivo, você perde o conteúdo. Mas se você abri-lo para leitura, então rmabrir o mesmo nome de caminho para gravação, você está na verdade criando um novo arquivo com o mesmo nome de caminho (mas em um novo inode e local de disco, já que o original ainda está aberto): então o conteúdo ainda está disponível.

Então, quando terminar, você pode fechar o descritor de arquivo aberto anteriormente (é isso que a exec 3<&-sintaxe especial faz), que libera o arquivo original para que o sistema operacional possa excluir (marcar como não utilizado) seu espaço em disco.

Ressalvas

Há algumas coisas que você deve ter em mente sobre esta solução:

  1. Você só pode "examinar" o conteúdo uma vez - não háportátilmaneira de um shell "procurar" de volta no descritor de arquivo - assim, quando um programa lê parte do conteúdo, outros programas verão apenas o restante do arquivo. E sedlerá o arquivo inteiro.

  2. Há uma pequena chance de seu arquivo original ser perdido se seu shell/script/sed for eliminado antes de terminar.

informação relacionada