Réponses:
Tu ne peux pas. Utilisez ed ou GNU sed ou perl, ou faites ce qu'ils font en arrière-plan, c'est-à-dire créer un nouveau fichier pour le contenu.
ed
portable:
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
, création d'un nouveau fichier (recommandé, car si votre script est interrompu, vous pouvez simplement le relancer):
cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo
cut
, en remplaçant le fichier en place (conserve la propriété et les autorisations de foo
, mais a besoin d'une protection contre les interruptions):
cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old
Je recommande d'utiliser l'une des cut
méthodes basées sur. De cette façon, vous ne dépendez d'aucun outil non standard, vous pouvez utiliser le meilleur outil pour le travail et vous contrôlez le comportement en cas d'interruption.
cut -d , -f 1,3 foo > foo.new
rm foo
mv foo.new foo
rm foo
. Et vous ne devriez pas appeler rm foo
, car il mv foo.new foo
est atomique: il supprime l'ancienne version et met la nouvelle version en place en même temps.
Le paquet moreutils d'ubuntu (et aussi de debian ) a un programme appelé sponge
, qui résout en quelque sorte votre problème.
De l'homme éponge:
l'éponge lit l'entrée standard et l'écrit dans le fichier spécifié. Contrairement à une redirection de shell, l'éponge absorbe toutes ses entrées avant d'ouvrir le fichier de sortie. Cela permet de restreindre les pipelines qui lisent et écrivent dans le même fichier.
Ce qui vous permettrait de faire quelque chose comme:
cut -d <delim> -f <fields> somefile | sponge somefile
Je ne pense pas que ce soit possible en utilisant cut
seul. Je ne pouvais pas le trouver dans la page man ou info. Vous pouvez faire quelque chose comme
mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file
mktemp
fait de vous un fichier temporaire relativement sûr dans lequel vous pouvez diriger la cut
sortie.
Vous pouvez utiliser slurp avec POSIX Awk:
cut -b1 file | awk 'BEGIN{RS="";getline<"-";print>ARGV[1]}' file
Eh bien, puisque cut
produit moins de sortie qu'il n'en lit, vous pouvez faire:
cut -c1 < file 1<> file
C'est-à-dire, rendre son stdin file
ouvert en mode lecture seule et son stdout file
ouvert en mode lecture + écriture sans troncature ( <>
).
De cette façon, cut
écrasera simplement le fichier sur lui-même. Cependant, cela laissera le reste du fichier intact. Par exemple, si file
contient:
foo
bar
La sortie deviendra:
f
b
bar
L' f\nb\n
ont remplacé foo\n
, mais bar
est toujours là. Vous devez tronquer le fichier une fois cut
terminé.
Avec ksh93
, vous pouvez le faire avec son <>;
opérateur qui agit comme <>
sauf que si la commande réussit, ftruncate()
est appelée sur le descripteur de fichier. Donc:
cut -c1 < file 1<>; file
Avec d'autres obus, vous devez effectuer la ftruncate()
via d'autres moyens comme:
{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file
bien qu'invoquer perl
juste pour cela est un peu exagéré ici, d'autant plus que cela perl
peut facilement faire ce cut
travail comme:
perl -pi -e '$_ = substr($_, 0, 1)' file
Attention, avec toutes les méthodes qui impliquent une réécriture réelle sur place, si l'opération est interrompue à mi-chemin, vous vous retrouverez avec un fichier corrompu. L'utilisation d'un deuxième fichier temporaire évite ce problème.
.old
méthode pour les changements sur place,echo "$(cut -d , -f 1,3 <foo)" > foo