У меня есть текстовый файл, содержащий одно имя файла в каждой строке:
111_c4l5r120.png 123_c4l4r60.png 135_c4l4r180.png 147_c4l3r60.png 15_c4l1r120.png ...
Я хочу преобразовать его в эту форму:
111_c4l5r120.png 111 123_c4l4r60.png 123 135_c4l4r180.png 135 147_c4l3r60.png 147 15_c4l1r120.png 15 ...
используя этот код:
#!/bin/bash while IFS='' read -r line || [[ -n "$line" ]]; do echo "$line" >> output.txt echo "$line" | cut -d'_' -f 1 >> output.txt done < "$1"
но результат:
111_c4l5r120.png 111 123_c4l4r60.png 123 135_c4l4r180.png 135 147_c4l3r60.png 147 15_c4l1r120.png 15 ...
Как мне изменить свой сценарий, чтобы получить желание?
Если у вас нет конкретной необходимости использовать оболочку для этого, ответ тердона дает лучшие альтернативы.
Поскольку вы используете bash
(как указано в shebang скрипта), вы можете использовать параметр -n
для эха:
echo -n "${line} " >> output.txt echo "$line" | cut -d'_' -f 1 >> output.txt
Или вы можете использовать функции оболочки для обработки строки без использования cut
:
echo "${line} ${line%%_*}" >> output.txt
(заменяя обе echo
линии).
Кроме того, printf
тоже будет делать трюк, работает в любой оболочке POSIX и, как правило, лучше (см. Раздел «Почему printf лучше, чем эхо?» ):
printf "%s " "${line}" >> output.txt echo "$line" | cut -d'_' -f 1 >> output.txt
или
printf "%s %s\n" "${line}" "${line%%_*}" >> output.txt
(Строго говоря, в plain /bin/sh
, echo -n
не переносится . Поскольку вы явно используете bash
здесь все ОК).
Не делай этого в оболочке! Он гораздо сложнее, чем необходимо, подвержен ошибкам и далеко, далеко, медленнее. Существует множество инструментов, предназначенных для таких манипуляций с текстом. Например, в sed
(здесь, предполагая недавние реализации GNU или 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
Или, для любого 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
Вот ты где:
#!/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"
Вывод:
$ 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