Respostas:
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átil:
ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/
w
q
EOF
GNU sed
:
sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/' foo
Perl:
perl -i -l -F, -pae 'print @F[1,3]' foo
cut
, criando um novo arquivo (recomendado, porque se o seu script for interrompido, você poderá executá-lo novamente):
cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo
cut
, substituindo o arquivo no lugar (mantém a propriedade e as permissões de foo
, mas precisa de proteção contra interrupções):
cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old
Eu recomendo usar um dos cut
métodos baseados em. Dessa forma, você não depende de nenhuma ferramenta não padrão, pode usar a melhor ferramenta para o trabalho e controlar o comportamento em interrupção.
cut -d , -f 1,3 foo > foo.new
rm foo
mv foo.new foo
rm foo
. E você não deve ligar rm foo
, porque mv foo.new foo
é atômico: remove a versão antiga e coloca a nova versão ao mesmo tempo.
O pacote moreutils do ubuntu (e também do debian ) tem um programa chamado sponge
, que também resolve o seu problema.
Da esponja do homem:
esponja lê a entrada padrão e a grava no arquivo especificado. Ao contrário de um redirecionamento de shell, a esponja absorve toda a sua entrada antes de abrir o arquivo de saída. Isso permite que os pipelines restritos sejam lidos e gravados no mesmo arquivo.
O que permitiria fazer algo como:
cut -d <delim> -f <fields> somefile | sponge somefile
Eu não acho que isso é possível usando cut
sozinho. Não consegui encontrá-lo na página de informações ou homem. Você pode fazer algo como
mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file
mktemp
faz de você um arquivo temporário relativamente seguro no qual você pode canalizar a cut
saída.
Você pode usar o slurp com o POSIX Awk:
cut -b1 file | awk 'BEGIN{RS="";getline<"-";print>ARGV[1]}' file
Bem, como cut
produz menos saída do que lê, você pode:
cut -c1 < file 1<> file
Ou seja, torne o stdin file
aberto no modo somente leitura e o stdout file
aberto no modo leitura + gravação sem truncamento ( <>
).
Dessa forma, cut
apenas substituirá o arquivo por si próprio. No entanto, ele deixará o restante do arquivo intocado. Por exemplo, se file
contém:
foo
bar
A saída se tornará:
f
b
bar
Eles f\nb\n
foram substituídos foo\n
, mas bar
ainda estão lá. Você precisaria truncar o arquivo após a cut
conclusão.
Com ksh93
, você pode fazê-lo com seu <>;
operador, que age como <>
exceto, se o comando for bem-sucedido, ftruncate()
é chamado no descritor de arquivo. Então:
cut -c1 < file 1<>; file
Com outras conchas, você precisaria fazer isso ftruncate()
através de outros meios, como:
{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file
embora invocar perl
apenas para isso seja um pouco exagerado aqui, especialmente considerando que perl
pode facilmente fazer esse cut
trabalho, como:
perl -pi -e '$_ = substr($_, 0, 1)' file
Lembre-se de que, com todos os métodos que envolvem a reescrita no local real, se a operação for interrompida no meio do caminho, você acabará com um arquivo corrompido. O uso de um segundo arquivo temporário evita esse problema.
.old
método para mudanças no local,echo "$(cut -d , -f 1,3 <foo)" > foo