¿Cómo eliminar \n entre las salidas de dos comandos de eco?

¿Cómo eliminar \n entre las salidas de dos comandos de eco?

Tengo un archivo de texto que contiene un nombre de archivo en cada línea:

111_c4l5r120.png
123_c4l4r60.png
135_c4l4r180.png
147_c4l3r60.png
15_c4l1r120.png
...

Quiero convertirlo en esta forma:

111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
...

usando este código:

#!/bin/bash
while IFS='' read -r line || [[  -n "$line"  ]]; do
   echo "$line" >> output.txt   
   echo "$line" | cut -d'_' -f 1 >> output.txt
done < "$1"

pero el resultado es:

111_c4l5r120.png 
111
123_c4l4r60.png 
123
135_c4l4r180.png 
135
147_c4l3r60.png 
147
15_c4l1r120.png 
15
...

¿Cómo debo cambiar mi script para obtener el resultado deseado?

Respuesta1

¡No hagas este tipo de cosas en el caparazón! Es mucho más complejo de lo necesario, propenso a errores y mucho, mucho, más lento. Existen muchas herramientas diseñadas para este tipo de manipulación de texto. Por ejemplo, en sed(aquí asumiendo implementaciones recientes de GNU o BSD para -E):

$ sed -E 's/([^_]*).*/& \1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

O, para cualquiera sed:

$ sed 's/\([^_]*\).*/& \1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

Perla:

$ perl -pe 's/(.+?)_.*/$& $1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

mal:

$ awk -F_ '{print $0,$1}' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

Respuesta2

A menos que tenga una necesidad específica de utilizar el shell para esto,la respuesta de terdónofrece mejores alternativas.

Ya que estás usando bash(como se indica en el shebang del script), puedes usar la -nopción para hacer eco:

echo -n "${line} " >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt

O puede usar funciones de Shell para procesar la línea sin usar cut:

echo "${line} ${line%%_*}" >> output.txt

(reemplazando ambas echolíneas).

Alternativamente, printftambién funcionaría, funciona en cualquiershell POSIX, y generalmente es mejor (ver¿Por qué printf es mejor que echo?para detalles):

printf "%s " "${line}" >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt

o

printf "%s %s\n" "${line}" "${line%%_*}" >> output.txt

(Estrictamente hablando, en términos sencillos /bin/sh,echo -nno es portatil. Ya que lo estás usando explícitamente, bashestá bien aquí).

Respuesta3

Aquí estás:

#!/bin/bash

while IFS='' read -r line || [[  -n "$line"  ]]; do
   echo "$line" `echo "$line" | cut -d'_' -f 1` >> output.txt
#   echo "$line" | cut -d'_' -f 1 >> output.txt
done < "$1"

Producción:

$ rm -rf output.txt
$ ./test.sh 1.1; cat output.txt
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

información relacionada