Как удалить \ n между выводами двух эхо-команд?


13

У меня есть текстовый файл, содержащий одно имя файла в каждой строке:

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
...

Как мне изменить свой сценарий, чтобы получить желаемый результат?


Google находит лучшие результаты, например, это .
Томас Дики

Ответы:


17

Если у вас нет особой необходимости использовать оболочку для этого, ответ Тердона предлагает лучшие альтернативы.

Поскольку вы используете bash(как указано в сценарии), вы можете использовать -nпараметр echo:

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

Или вы можете использовать функции оболочки для обработки строки без использования cut:

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

(замена обеих echoстрок).

В качестве альтернативы, printfтоже бы сработал, работает в любой оболочке POSIX и, как правило, лучше (см. Подробнее, почему printf лучше, чем echo? ):

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

или

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

(Строго говоря, простыми словами /bin/sh, echo -nон не переносимый . Так как вы явно используете bash, здесь все в порядке.)


Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Тердон

23

Не делай такого рода вещи в оболочке! Это намного сложнее, чем необходимо, подвержено ошибкам и намного, намного медленнее. Есть много инструментов, предназначенных для такой обработки текста. Например, в 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

1
Внешние утилиты не намного лучше, хотя.
EKons

6
@ ΈρικΚωνσταντόπουλος да, они есть. На несколько порядков быстрее, на самом деле. Оболочка просто не очень хороша в подобных вещах. В конце концов, основная задача оболочки - запуск внешних утилит. Сравните время, затрачиваемое подходом OP, с тем, которое используется любым из решений здесь. Оболочки петли очень и очень медленные. Если вам нужно больше убедительности, прочитайте это .
Terdon

С точки зрения мобильности, нет. С точки зрения скорости, да. Кроме того, @ StéphaneChazelas ваш псевдоним?
EKons

4
@ ΈρικΚωνσταντόπουλος Θα 'θελα :) Нет, он просто написал 2 отличных ответа, относящихся к двум веткам комментариев. Что касается переносимости, за исключением (незначительного) подхода perl, который будет работать только на ~ 90% машин * nix, все три решения являются переносимыми и не зависят от оболочки. Или, хорошо, вы всегда можете сделать sedодин в sed 's/\([^_]*\).*/& \1/' fileдля дополнительной портативности. Дело в том, что вы можете рассчитывать awkи sedбыть там больше, чем вы можете рассчитывать почти на все остальное.
Terdon

2

А, вот и ты:

#!/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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.