Як видалити \ 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 -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

(Власне кажучи, звичайно /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
@ ΈρικΚωνσταντόπουλος так вони є. Насправді на кілька порядків швидше. Оболонка просто не дуже хороша в подібних речах. Основна робота оболонки - це запуск зовнішніх утиліт. Порівняйте час, зайнятий підходом ОП, з тим, який було прийнято будь-яким із наведених тут рішень. Раковини петель дуже, дуже повільні. Якщо вам потрібно більш переконливо, прочитайте це .
terdon

З точки зору портативності, немає. З точки зору швидкості, так. Також @ StéphaneChazelas ваш псевдонім?
EKons

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

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.