sustituir script manejo linea leer insertar fichero especiales espacios eliminar comando caracteres cadenas blanco bash parsing text-files cat

script - Preservar el espacio en blanco al leer>> escribir un archivo línea por línea en bash



sed eliminar espacios en blanco (5)

Como otros han señalado, usar cat o awk en lugar de un loop de lectura-eco es una forma mucho mejor de hacerlo: evita el problema del recorte del espacio en blanco (y un par de otros con los que no se ha tropezado), corre más rápido, y al menos con cat, es simplemente un código más limpio. No obstante, me gustaría intentar conseguir que el ciclo de lectura y eco funcione correctamente.

Primero, el problema del recorte del espacio en blanco: el comando de lectura recorta automáticamente el espacio en blanco inicial y final; esto puede solucionarse cambiando su definición de espacios en blanco al establecer la variable IFS en blanco. Además, read asume que una barra invertida al final de la línea significa que la siguiente línea es una continuación, y debe empalmarse con esta; para arreglar esto, use su indicador -r (raw). El tercer problema aquí es que muchas implementaciones de echo interpretan secuencias de escape en la cadena (por ejemplo, pueden convertir / n en una nueva línea real); para arreglar esto, use printf en su lugar. Finalmente, al igual que una regla general de higiene de secuencias de comandos, no debe usar cat cuando no lo necesite; use la redirección de entrada en su lugar. Con esos cambios, el lazo interno se ve así:

while IFS='''' read -r line; do printf "%s/n" "$line">>$OUTPUT done <$f

... también hay un par de otros problemas con el guión circundante: la línea que intenta definir ARCHIVOS como la lista de archivos .textile disponibles tiene comillas a su alrededor, lo que significa que nunca se expande en una lista real de archivos. La mejor forma de hacerlo es usar una matriz:

FILES=(../best-practices/*.textile) ... for f in "${FILES[@]}"

(y todas las apariciones de $ f deben estar entre comillas dobles en caso de que alguno de los nombres de los archivos tenga espacios u otros caracteres divertidos en ellas, también debería hacerlo con $ OUTPUT, aunque como está definido en el script, es seguro dejar fuera.)

Finalmente, hay un echo "">$OUTPUT cerca de la parte superior de los archivos loop-over-files que va a borrar el archivo de salida cada vez que pasa (es decir, al final, solo contiene el último archivo .textile); esto necesita moverse antes del ciclo. No estoy seguro de si la intención aquí fue poner una sola línea en blanco al comienzo del archivo, o tres líneas en blanco entre los archivos (y uno al principio y dos al final), así que no estoy seguro exactamente qué el reemplazo apropiado es De todos modos, aquí es lo que puedo hacer después de solucionar todos estos problemas:

#!/bin/sh OUTPUT="../best_practices.textile" FILES=(../best-practices/*.textile) : >"$OUTPUT" for f in "${FILES[@]}" do echo "Processing $f file..." echo >>"$OUTPUT" while IFS='''' read -r line; do printf "%s/n" "$line">>"$OUTPUT" done <"$f" echo >>"$OUTPUT" echo >>"$OUTPUT" done

Estoy intentando recorrer un directorio de archivos de texto y combinarlos en un solo documento. Esto funciona muy bien, pero los archivos de texto contienen fragmentos de código, y todo mi formato está colapsado hacia la izquierda. Se eliminan todos los espacios en blanco iniciales en una línea.

#!/bin/sh OUTPUT="../best_practices.textile" FILES="../best-practices/*.textile" for f in "$FILES" do echo "Processing $f file..." echo "">$OUTPUT cat $f | while read line; do echo "$line">>$OUTPUT done echo >>$OUTPUT echo >>$OUTPUT done

Definitivamente soy un novato bash, pero después de buscar alto y bajo no pude encontrar una solución adecuada. Aparentemente BASH odia el espacio blanco líder en general.


Esto le permite intercalar líneas nuevas entre cada archivo de entrada como lo ha hecho en su secuencia de comandos original:

for f in $FILES; do echo -ne ''/n/n'' | cat "$f" -; done > $OUTPUT

Tenga en cuenta que $FILES no está citado para que esto funcione (de lo contrario, las nuevas líneas adicionales aparecen solo una vez al final de todos los resultados), pero debe citarse $f para proteger espacios en nombres de archivos, si existen.


esa es una forma demasiado costosa de combinar archivos.

cat ../best-practices/*.textile > ../best_practices.textile

si desea agregar un espacio en blanco (nueva línea) a cada archivo a medida que concatenan, use awk

awk ''FNR==1{print "">"out.txt"}{print > "out.txt" }'' *.textile

O

awk ''FNR==1{print ""}{print}'' file* > out.txt


En lugar de:

cat $f | while read line; do echo "$line">>$OUTPUT done

Hacer esto:

cat $f >>$OUTPUT

(Si hay una razón por la que necesita hacer las cosas línea por línea, sería bueno incluir eso en la pregunta).


La respuesta correcta, imo, es esta , reproducida a continuación:

while IFS= read line; do check=${line:0:1} done < file.txt

Tenga en cuenta que se encargará de situaciones en las que la entrada se canaliza desde otro comando, y no solo desde un archivo real.

Tenga en cuenta que también puede simplificar la redirección como se muestra a continuación.

#!/bin/bash OUTPUT="../best_practices.textile" FILES="../best-practices/*.textile" for f in "$FILES" do echo "Processing $f file..." { echo while IFS= read line; do echo "$line" done < $f echo echo; } > $OUTPUT done