Баш: как подавить переводы строки? - PullRequest
1 голос
/ 13 марта 2010

Я пытаюсь извлечь поля из файла с разделителями канала и предоставить их в качестве аргументов внешней программе в цикле. Файл содержит такие строки:

value1|value2
value3|value4

Итак, я придумал:

 while read line;

    do echo -n "${line}" | awk -F '|' '{print $1}';
       echo -n " something ";
       echo -n "${line}" | awk -F '|' '{print $2}';
       echo " somethingelse";

 done < <(cat $FILE)

Я хочу увидеть следующий вывод:

value1 something value2 somethingelse
value3 something value4 somethingelse

Но вместо этого я получаю:

value1 
 something value2
 somethingelse
value3
 something value4
 somethingelse

Может быть, я не должен использовать эхо?

Ответы [ 4 ]

2 голосов
/ 13 марта 2010

Если ваш awk поддерживает printf, я бы использовал это вместо этого. Даже если echo -n не добавляет символ новой строки, awk {print} добавляет. Вариант printf не ставит символ новой строки в конце, как print:

echo -n "${line}" | awk -F '|' '{printf "%s", $1}'

Вот ваша версия в шестнадцатеричном формате, обратите внимание на \n в конце, когда вы проходите через awk:

pax> echo -n "hello|goodbye" | od -xcb
0000000    6568    6c6c    7c6f    6f67    646f    7962    0065
          h   e   l   l   o   |   g   o   o   d   b   y   e
        150 145 154 154 157 174 147 157 157 144 142 171 145
0000015

pax> echo -n "hello|goodbye" | awk -F '|' '{print $1}' | od -xcb
0000000    6568    6c6c    0a6f
          h   e   l   l   o  \n
        150 145 154 154 157 012

и вот printf версия:

pax> echo -n "hello|goodbye" | awk -F '|' '{printf "%s", $1}' | od -xcb
0000000    6568    6c6c    006f
          h   e   l   l   o
        150 145 154 154 157

И вот он работает на вашем реальном файле (в данном примере с именем FILE, чтобы облегчить мое тестирование):

pax> while read line;
     do
         echo -n "${line}" | awk -F '|' '{printf "%s", $1}';
         echo -n " something ";
         echo -n "${line}" | awk -F '|' '{printf "%s", $2}';
         echo " somethingelse";
     done < <(cat FILE)

value1 something value2 somethingelse
value3 something value4 somethingelse
1 голос
/ 13 марта 2010

@ OP, нет необходимости использовать cat. Также в цикле while вы можете установить IFS (разделитель входных полей) на pipe |, и нет необходимости использовать внешние команды для каждой проанализированной строки. Это неэффективно. Вот как это сделать только с оболочкой

while IFS="|" read -r a b
do
   echo "$a something $b somethingelse" # use echo without -n
done <"file"

Вы также можете использовать printf, который является более портативным, чем echo.

выход

$ ./shell.sh
value1 something value2 somethingelse
value3 something value4 somethingelse
0 голосов
/ 13 марта 2010
while read line;
    do
            echo  "${line}" | sed  s/'|'/' something '/| sed  s/$/' somethingelse'/;
 done < file1
0 голосов
/ 13 марта 2010

Вы можете использовать sed для этого:

$ cat test
value1|value2
value3|value4
$ sed 's/|/ something /; s/$/ somethingelse/' test
value1 something value2 somethingelse
value3 something value4 somethingelse
$

Обновление: Для исходного вопроса вы можете удалить новые строки с помощью tr -d '\012', например,

cat ${FILE} | while read line
do
        echo "${line}" | awk -F '|' '{print $1}' | tr -d '\012'
        echo -n " something "
        echo "${line}" | awk -F '|' '{print $2}' | tr -d '\012'
        echo " somethingelse"
done
...