Como remover \ n entre as saídas de dois comandos de eco?

13

Eu tenho um arquivo de texto contendo um nome de arquivo em cada linha:

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

Eu quero convertê-lo desta 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"

mas o resultado é:

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

Como devo mudar meu script para ter o resultado desejado?

    
por Ali 01.06.2016 / 10:54

3 respostas

17

A menos que você tenha uma necessidade específica de usar o shell para isso, a resposta de terdon fornece melhores alternativas.

Como você está usando bash (como indicado no shebang do script), você pode usar a opção -n para echo:

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

Ou você pode usar recursos de shell para processar a linha sem usar cut :

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

(substituindo as duas linhas echo ).

Como alternativa, printf também funcionaria, em qualquer shell POSIX , e geralmente é melhor (veja Por que printf é melhor que echo? para detalhes):

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

ou

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

(Estritamente falando, na planície /bin/sh , echo -n não é portátil Como você está explicitamente usando bash , tudo bem.)

    
por 01.06.2016 / 10:58
23

Não faça esse tipo de coisa na casca! É muito mais complexo do que o necessário, propenso a erros e, de longe, mais lento. Existem muitas ferramentas projetadas para essa manipulação de texto. Por exemplo, em sed (aqui assumindo implementações recentes de GNU ou BSD para -E ):

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

Ou, para qualquer sed :

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

Perl:

$ 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

awk:

$ 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
    
por 01.06.2016 / 11:11
2

Aqui você está:

#!/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"

Saída:

$ 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
    
por 01.06.2016 / 21:36