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?
shell
shell-script
Ali
źródło
źródło
Odpowiedzi:
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ć-n
opcji echa:Lub możesz użyć funkcji powłoki do przetworzenia linii bez użycia
cut
:(zastępując obie
echo
linie).Ewentualnie
printf
zrobił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? ):lub
(Ściśle rzecz biorąc, w zwykły
/bin/sh
,echo -n
nie jest przenośny . Skoro jesteś jawnie przy użyciubash
Jest OK tutaj).źródło
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
):Lub dla dowolnego
sed
:Perl:
awk:
źródło
sed
jedną dosed 's/\([^_]*\).*/& \1/' file
dodatkowych przenośności. Chodzi o to, że możesz liczyćawk
ised
będąc tam więcej niż możesz liczyć na prawie wszystko inne.Tu masz:
Wynik:
źródło