Es importante destacar :>que no es un solo operador. Puede ser más fácil de entender si lo lees como en su : > filelugar.
jpfx1342
Esto significa que la persona que escribe el guión debería haber redirigido la salida del bucle en el archivo: while read A B C D E; do echo "$A;$B;$D;$E;$C"; done < otherfile > file. O mejor aún, deberían haber utilizado la herramienta adecuada para el trabajo, awk, como lo sugirió Peter . Como comentario aparte, casi siempre quieres usar el -rinterruptor conread .
Tom Fenech
Fuera de fiesta, sería un smiley para un cuervo.
smci
Respuestas:
46
Había:> en una línea de un script bash. Qué significa eso?
:> file
Es una forma abreviada de decir:
Si fileno existe, créelo; de lo contrario, truncarlo en 0bytes.
Esto significa que puede estar seguro de que fileexiste y está vacío.
También puedes usarlo > filepero :> filees más portátil.
No entiendo la segunda línea. Pensé que leer leer variables. El eco del comando también es extraño. ¿Podrías explicar?
diego9403
No soy un experto en Unix, pero creo que la segunda línea lee cosas otherfiley las echoenvía file. También crea variables a partir de lo que lea ... Si desea una respuesta definitiva, haga su propia pregunta.
DavidPostill
2
@ diego9403: readobtiene información de stdin. Por sí solo, leería lo que escribe. Dado que stdin se ha redirigido a, <otherfileentonces el contenido de otherfile"se escribe" en stdin. Entonces readobtiene los valores línea por línea en las variables $ A, $ B, $ C, $ D y $ E.
slebetman
Entonces, ¿es solo una alternativa más oscura truncatede coreutils?
Federico Poloni
1
@PeterCordes No quise decir "oscuro" como en "es poco común", sino como "es menos claro para el lector".
Federico Poloni
29
Parece una forma elegante de crear un nuevo archivo. En bash:es un comando nulo:
$ type :: is a shell builtin
$ help ::::Null command.No effect; the command does nothing.ExitStatus:Always succeeds.
:es la abreviatura true. Posiblemente en algunas conchas, true¿no está incorporado? Ambos son incorporados en bash.
Peter Cordes
12
:es otro nombre para true. Ambas son conchas incorporadas en bash, pero no hay /bin/:, solo a /bin/true. La redirección de salida provoca el shell al open(2)archivo con O_CREAT|O_TRUNC. Si no se escribe nada, permanece en longitud cero.
Poner esas dos piezas juntas :> filees un modismo bastante común para truncar archivos. Sin embargo, la mayoría de la gente trataría de hacerlo menos extraño escribiendo : >file.
Como me preguntaste en un comentario sobre la segunda línea, convertiré mis comentarios en una respuesta. (aunque no hiciste esto en tu pregunta).
La segunda línea es un bucle que lee líneas de otherfilealgunas variables con nombre. El cuerpo del bucle se usa echopara imprimirlos con ;separadores en lugar de cualquier espacio en blanco que tenían antes. filese cierra y se vuelve a abrir (para agregar) cada iteración, porque la redirección está dentro del bucle. El uso while ...;do read -r ...;done <otherfile >filesería menos difícil y evitaría la necesidad de truncar primero el archivo. read -rno come \como un personaje de escape.
El procesamiento de texto en bash es bastante lento. Parte de eso es inevitable: readtiene que ir un byte a la vez (una read(2)llamada al sistema por byte) para evitar sobrepasar el final de una línea. Sería mejor usar la herramienta adecuada para el trabajo:
--significa que su script no se rompe si otherfilese le llama algo tonto --version.
Establecer el Separador de campo de salida en ;significa que puede pasar varios campos como argumentos para imprimir. Shell readasigna todo el resto de la línea con espacios en blanco a la última variable, pero no hay forma de decirle a awk que solo se divida en 5. Si eso es importante, tal vez solo siga usando un bucle bash, porque no es conveniente en awk. Perl lo hace fácil, ya que splitpuede tomar un argumento de campos máximos, pero es mucho más lento para iniciar que awk.
En realidad, resultó no ser tan difícil, solo una expresión regular fea para escribir. Para obtener el resto de la línea en lugar de $5en awk, recorrer los campos aún pierde su espacio en blanco original. Mi primera idea viable es usar gensuben $0(toda la línea) para eliminar los primeros 4 campos (es decir, sin espacio seguido de espacio), dejando todo lo demás:
Lo hice bien en el primer intento, pero el hecho de que estaba impresionado conmigo mismo por eso dice algo sobre la legibilidad de ese código awk. >. <
Tenga en cuenta que es igual printque antes, pero con tailen lugar de $5.
echo 'A B c DD e f g f'|
awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
print $1, $2, $4, tail, $3 }'
A;B;DD;e f g f;c
Esto sería más impresionante si pudiera copiar / pegar el literal y mostrar que apareció en la salida. Escriba uno en bash con ^ Q. ctrl-Q significa Citar la siguiente pulsación de tecla como un carácter literal, ya que la edición de línea al estilo de emacs de bash es la misma que la de emacs real para esto.
http://mywiki.wooledge.org/BashFAQ tiene algunas cosas útiles acerca de las secuencias de comandos de manera que no se rompan sin importar qué datos o nombres de archivos arrojes a la secuencia de comandos.
:>
que no es un solo operador. Puede ser más fácil de entender si lo lees como en su: > file
lugar.while read A B C D E; do echo "$A;$B;$D;$E;$C"; done < otherfile > file
. O mejor aún, deberían haber utilizado la herramienta adecuada para el trabajo, awk, como lo sugirió Peter . Como comentario aparte, casi siempre quieres usar el-r
interruptor conread
.Respuestas:
Había:> en una línea de un script bash. Qué significa eso?
Es una forma abreviada de decir:
file
no existe, créelo; de lo contrario, truncarlo en0
bytes.Esto significa que puede estar seguro de que
file
existe y está vacío.También puedes usarlo
> file
pero:> file
es más portátil.Vea la pregunta de desbordamiento de pila ¿Cuál es el propósito de la ':' (colon) GNU Bash Builtin? para más información.
fuente
otherfile
y lasecho
envíafile
. También crea variables a partir de lo que lea ... Si desea una respuesta definitiva, haga su propia pregunta.read
obtiene información de stdin. Por sí solo, leería lo que escribe. Dado que stdin se ha redirigido a,<otherfile
entonces el contenido deotherfile
"se escribe" en stdin. Entoncesread
obtiene los valores línea por línea en las variables $ A, $ B, $ C, $ D y $ E.truncate
de coreutils?Parece una forma elegante de crear un nuevo archivo. En
bash
:
es un comando nulo:>
redirige la salida de:
a un archivo.fuente
>
hace:
es la abreviaturatrue
. Posiblemente en algunas conchas,true
¿no está incorporado? Ambos son incorporados en bash.:
es otro nombre paratrue
. Ambas son conchas incorporadas en bash, pero no hay/bin/:
, solo a/bin/true
. La redirección de salida provoca el shell alopen(2)
archivo conO_CREAT|O_TRUNC
. Si no se escribe nada, permanece en longitud cero.Poner esas dos piezas juntas
:> file
es un modismo bastante común para truncar archivos. Sin embargo, la mayoría de la gente trataría de hacerlo menos extraño escribiendo: >file
.Como me preguntaste en un comentario sobre la segunda línea, convertiré mis comentarios en una respuesta. (aunque no hiciste esto en tu pregunta).
La segunda línea es un bucle que lee líneas de
otherfile
algunas variables con nombre. El cuerpo del bucle se usaecho
para imprimirlos con;
separadores en lugar de cualquier espacio en blanco que tenían antes.file
se cierra y se vuelve a abrir (para agregar) cada iteración, porque la redirección está dentro del bucle. El usowhile ...;do read -r ...;done <otherfile >file
sería menos difícil y evitaría la necesidad de truncar primero el archivo.read -r
no come\
como un personaje de escape.El procesamiento de texto en bash es bastante lento. Parte de eso es inevitable:
read
tiene que ir un byte a la vez (unaread(2)
llamada al sistema por byte) para evitar sobrepasar el final de una línea. Sería mejor usar la herramienta adecuada para el trabajo:--
significa que su script no se rompe siotherfile
se le llama algo tonto--version
.Establecer el Separador de campo de salida en
;
significa que puede pasar varios campos como argumentos para imprimir. Shellread
asigna todo el resto de la línea con espacios en blanco a la última variable, pero no hay forma de decirle a awk que solo se divida en 5. Si eso es importante, tal vez solo siga usando un bucle bash, porque no es conveniente en awk. Perl lo hace fácil, ya quesplit
puede tomar un argumento de campos máximos, pero es mucho más lento para iniciar que awk.En realidad, resultó no ser tan difícil, solo una expresión regular fea para escribir. Para obtener el resto de la línea en lugar de
$5
en awk, recorrer los campos aún pierde su espacio en blanco original. Mi primera idea viable es usargensub
en$0
(toda la línea) para eliminar los primeros 4 campos (es decir, sin espacio seguido de espacio), dejando todo lo demás:Lo hice bien en el primer intento, pero el hecho de que estaba impresionado conmigo mismo por eso dice algo sobre la legibilidad de ese código awk. >. <
Tenga en cuenta que es igual
print
que antes, pero contail
en lugar de$5
.Esto sería más impresionante si pudiera copiar / pegar el literal y mostrar que apareció en la salida. Escriba uno en bash con ^ Q. ctrl-Q significa Citar la siguiente pulsación de tecla como un carácter literal, ya que la edición de línea al estilo de emacs de bash es la misma que la de emacs real para esto.
http://mywiki.wooledge.org/BashFAQ tiene algunas cosas útiles acerca de las secuencias de comandos de manera que no se rompan sin importar qué datos o nombres de archivos arrojes a la secuencia de comandos.
fuente