Posso fazer 'cortar' alterar um arquivo no lugar?

13

A man page não me dá muita esperança, mas estou esperando que seja um recurso não documentado (e / ou específico do GNU).

    
por Hank Gay 13.01.2011 / 23:42

6 respostas

14

Você não pode. Use ed ou GNU sed ou perl, ou faça o que eles fazem nos bastidores, que é criar um novo arquivo para o conteúdo.

ed , portável:

ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/,/
w
q
EOF

GNU sed :

sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/,/' foo

Perl:

perl -i -l -F, -pae 'print @F[1,3]' foo

cut , criando um novo arquivo (recomendado, porque se seu script for interrompido, você pode simplesmente executá-lo novamente):

mv foo foo.old
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old

cut , substituindo o arquivo em vigor (mantém a propriedade e as permissões de foo , mas precisa de proteção contra interrupções):

cp foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old

Eu recomendo usar um dos métodos cut -based. Dessa forma, você não depende de nenhuma ferramenta não padrão, pode usar a melhor ferramenta para o trabalho e controla o comportamento na interrupção.

    
por 14.01.2011 / 00:13
18

O pacote moreutils do Ubuntu (e também debian ) tem um programa chamado sponge , que também resolve seu problema.

Da esponja do homem:

sponge reads standard input and writes it out to the specified file. Unlike a shell redirect, sponge soaks up all its input before opening the output file. This allows constricting pipelines that read from and write to the same file.

O que permitiria que você fizesse algo como:

cut -d <delim> -f <fields> somefile | sponge somefile
    
por 14.01.2011 / 10:27
9

Eu não acho que seja possível usar cut sozinho. Eu não consegui encontrá-lo no homem ou na página de informações. Você pode fazer algo como

mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file

mktemp torna você um arquivo temporário relativamente seguro no qual você pode canalizar a saída cut .

    
por 14.01.2011 / 00:05
1

Experimente o vim-way:

$ ex -s +'%!cut -c 1-10' -cxa file.txt

Isto irá editar o arquivo no local (assim como o backup primeiro).

Como alternativa, use grep , sed ou gawk .

    
por 19.04.2015 / 22:48
0

Você pode usar o slurp com o POSIX Awk:

cut -b1 file | awk 'BEGIN{RS="";getline<"-";print>ARGV[1]}' file

Exemplo

    
por 15.01.2017 / 21:25
0

Bem, como cut produz menos resultados do que lê, você pode fazer:

cut -c1 < file 1<> file

Isto é, torne seu stdin o file aberto no modo somente leitura e seu stdout file é aberto no modo de leitura + gravação sem truncamento ( <> ).

Dessa forma, cut apenas sobrescreverá o arquivo. No entanto, deixará o resto do arquivo intacto. Por exemplo, se file contiver:

foo
bar

A saída será:

f
b
bar

O f\nb\n substituiu foo\n , mas bar ainda está lá. Você precisaria truncar o arquivo depois que cut terminar.

Com ksh93 , você pode fazer isso com seu operador <>; , que age como <> , exceto que, se o comando for bem-sucedido, ftruncate() será chamado no descritor de arquivo. Então:

cut -c1 < file 1<>; file

Com outros shells, você precisa fazer o ftruncate() por meio de outros meios, como:

{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file

embora chamar perl apenas para isso é um pouco exagerado, especialmente considerando que perl pode facilmente fazer o trabalho de cut como:

perl -pi -e '$_ = substr($_, 0, 1)' file

Tenha em atenção que, com todos os métodos que envolvem reescrita real no local, se a operação for interrompida a meio caminho, terminará com um ficheiro danificado. Usar um segundo arquivo temporário evita esse problema.

    
por 15.01.2017 / 22:20