Respuestas:
No puedes Utilice ed o GNU sed o perl, o haga lo que hacen detrás de escena, que es crear un nuevo archivo para el contenido.
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
, creando un nuevo archivo (recomendado, porque si su secuencia de comandos se interrumpe, puede ejecutarla nuevamente):
cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo
cut
, reemplazando el archivo en su lugar (conserva la propiedad y los permisos de foo
, pero necesita protección contra interrupciones):
cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old
Recomiendo usar uno de los cut
métodos basados. De esa manera, no depende de ninguna herramienta no estándar, puede usar la mejor herramienta para el trabajo y controlar el comportamiento en la interrupción.
cut -d , -f 1,3 foo > foo.new
rm foo
mv foo.new foo
rm foo
. Y no debe llamar rm foo
, porque mv foo.new foo
es atómico: elimina la versión anterior y coloca la nueva versión al mismo tiempo.
El paquete moreutils de ubuntu (y también debian ) tiene un programa llamado sponge
, que también resuelve su problema.
De hombre esponja:
la esponja lee la entrada estándar y la escribe en el archivo especificado. A diferencia de una redirección de shell, la esponja absorbe toda su entrada antes de abrir el archivo de salida. Esto permite restringir las tuberías que leen y escriben en el mismo archivo.
Lo que te permitiría hacer algo como:
cut -d <delim> -f <fields> somefile | sponge somefile
No creo que sea posible usar cut
solo. No pude encontrarlo en el hombre o en la página de información. Puedes hacer algo como
mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file
mktemp
lo convierte en un archivo temporal relativamente seguro en el que puede canalizar la cut
salida.
Puede usar slurp con POSIX Awk:
cut -b1 file | awk 'BEGIN{RS="";getline<"-";print>ARGV[1]}' file
Bueno, dado que cut
produce menos salida de lo que lee, puede hacer:
cut -c1 < file 1<> file
Es decir, haga que su entrada estándar sea file
abierta en modo de solo lectura y que sea file
abierta en modo lectura + escritura sin truncamiento ( <>
).
De esa manera, cut
simplemente sobrescribirá el archivo sobre sí mismo. Sin embargo, dejará el resto del archivo intacto. Por ejemplo, si file
contiene:
foo
bar
La salida se convertirá en:
f
b
bar
La f\nb\n
han reemplazado foo\n
, pero bar
todavía está allí. Debería truncar el archivo una vez que cut
haya finalizado.
Con ksh93
, puede hacerlo con su <>;
operador, que actúa como, <>
excepto que si el comando tiene éxito, ftruncate()
se llama en el descriptor de archivo. Entonces:
cut -c1 < file 1<>; file
Con otros proyectiles, deberías hacerlo a ftruncate()
través de otros medios como:
{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file
aunque invocar perl
solo por eso es un poco exagerado, especialmente teniendo en cuenta que perl
puede hacer fácilmente ese cut
trabajo como:
perl -pi -e '$_ = substr($_, 0, 1)' file
Tenga en cuenta que con todos los métodos que implican una reescritura real en el lugar, si la operación se interrumpe a mitad de camino, terminará con un archivo dañado. El uso de un segundo archivo temporal evita este problema.
.old
método para los cambios en el lugar,echo "$(cut -d , -f 1,3 <foo)" > foo