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
...
Quero convertê-lo nesta 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 alterar meu script para obter a saída desejada?
Responder1
Não faça esse tipo de coisa na casca! É muito mais complexo do que o necessário, sujeito a erros e muito, muito 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/([^_]*).*/& \1/' 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/\([^_]*\).*/& \1/' 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
estranho:
$ 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
Responder2
A menos que você tenha uma necessidade específica de usar o shell para isso,resposta de Terdonoferece melhores alternativas.
Como você está usando bash
(conforme indicado no shebang do script), você pode usar a -n
opção de ecoar:
echo -n "${line} " >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt
Ou você pode usar recursos do shell para processar a linha sem usar cut
:
echo "${line} ${line%%_*}" >> output.txt
(substituindo ambas echo
as linhas).
Alternativamente, printf
também funcionaria, funciona em qualquerConcha POSIX, e geralmente é melhor (vejaPor 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, em termos simples /bin/sh
,echo -n
não é portátil. Como você está usando explicitamente, bash
tudo bem aqui.)
Responder3
Olha Você aqui:
#!/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