Jak usunąć \ n między wyjściami dwóch poleceń echa?

13

Mam plik tekstowy zawierający jedną nazwę pliku w każdej linii:

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

Chcę przekonwertować go na ten kształt:

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

za pomocą tego kodu:

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

ale wynikiem jest:

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

Jak powinienem zmienić skrypt, aby uzyskać pożądane wyniki?

Ali
źródło
Google znajduje lepsze wyniki, np . To .
Thomas Dickey,

Odpowiedzi:

17

O ile nie masz szczególnej potrzeby użycia powłoki do tego celu, odpowiedź terdona zapewnia lepsze alternatywy.

Ponieważ używasz bash(jak wskazano w skrócie skryptu), możesz użyć -nopcji echa:

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

Lub możesz użyć funkcji powłoki do przetworzenia linii bez użycia cut:

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

(zastępując obie echolinie).

Ewentualnie printfzrobiłby to samo, działa w dowolnej powłoce POSIX i ogólnie jest lepszy (więcej informacji na temat dlaczego printf jest lepszy niż echo? ):

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

lub

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

(Ściśle rzecz biorąc, w zwykły /bin/sh, echo -nnie jest przenośny . Skoro jesteś jawnie przy użyciu bashJest OK tutaj).

Stephen Kitt
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
terdon
23

Nie rób tego w skorupce! Jest znacznie bardziej skomplikowany niż to konieczne, podatny na błędy i znacznie, znacznie wolniejszy. Istnieje wiele narzędzi zaprojektowanych do takiej manipulacji tekstem. Na przykład w sed(tutaj przy założeniu, że dla GNU lub ostatnich implementacji BSD -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

Lub dla dowolnego 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

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
terdon
źródło
1
Narzędzia zewnętrzne nie są jednak znacznie lepsze.
EKons,
6
@ ΈρικΚωνσταντόπουλος tak, są. Właściwie kilka rzędów wielkości szybciej. Powłoka po prostu nie jest zbyt dobra w tego rodzaju rzeczach. W końcu głównym zadaniem powłoki jest uruchamianie zewnętrznych narzędzi. Porównaj czas poświęcony przez podejście PO z czasem zastosowanym przez którekolwiek z rozwiązań tutaj. Pętle muszli są bardzo, bardzo wolne. Jeśli potrzebujesz bardziej przekonujących, przeczytaj to .
terdon
Jeśli chodzi o przenośność, nie. Pod względem prędkości tak. Ponadto, czy @ StéphaneChazelas jest twoim pseudonimem?
EKons,
4
@ ΈρικΚωνσταντόπουλος Θα 'θελα :) Nie, on po prostu akurat napisał 2 świetne odpowiedzi, które były istotne dla dwóch wątków komentarzy. Jeśli chodzi o przenośność, z (niewielkim) wyjątkiem podejścia perl, które będzie działać tylko na około 90% * maszyn * nix, wszystkie trzy rozwiązania są przenośne i niezależne od powłoki. Albo, OK, zawsze można zrobić sedjedną do sed 's/\([^_]*\).*/& \1/' filedodatkowych przenośności. Chodzi o to, że możesz liczyć awki sedbędąc tam więcej niż możesz liczyć na prawie wszystko inne.
terdon
2

Tu masz:

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

Wynik:

$ 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
Putnik
źródło