Bash превращение многострочной строки в одну запятую


допустим, у меня есть следующая строка:

something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

Как мне превратить это в просто

+12.0,+15.5,+9.0,+13.5

в bash?

16 65

16 ответов:

можно использовать awk и sed:

awk -vORS=, '{ print  }' file.txt | sed 's/,$/\n/'

или если вы хотите использовать трубы:

echo "data" | awk -vORS=, '{ print  }' | sed 's/,$/\n/'

чтобы разбить его:

  • awk отлично справляется с обработкой данных, разбитых на поля
  • -vORS=, устанавливает "выходной разделитель записей" в ,, который является то, что вы хотели
  • { print } говорит awk для печати второго поля для каждой записи (строки)
  • file.txt ваш имя файла
  • sed просто избавляется от трейлинг , и превращает его в новую строку (если вы не хотите новой строки, вы можете сделать s/,$//)

чистый и простой:

awk '{print }' < file.txt | paste -s -d, -
$ awk -v ORS=, '{print }' data.txt | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

$ cat data.txt | tr -s ' ' | cut -d ' ' -f 2 | tr '\n' ',' | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

Это тоже должно работать

awk '{print }' file | sed ':a;{N;s/\n/,/};ba'

Это может сработать для вас:

cut -d' ' -f5 file | paste -d',' -s
+12.0,+15.5,+9.0,+13.5

или

sed '/^.*\(+[^ ]*\).*/{s///;H};${x;s/\n/,/g;s/.//p};d' file
+12.0,+15.5,+9.0,+13.5
cat data.txt | xargs | sed -e 's/ /, /g'

awk один лайнер

$ awk '{printf (NR>1?",":"") }' file

+12.0,+15.5,+9.0,+13.5

попробуйте это:

sedSelectNumbers='s".* \(+[0-9]*[.][0-9]*\) .*","'
sedClearLastComma='s"\(.*\),$""'
cat file.txt |sed "$sedSelectNumbers" |tr -d "\n" |sed "$sedClearLastComma"

хорошая вещь-это легкая часть удаления символов новой строки "\n"!

EDIT: еще один отличный способ объединить строки в одну строку с sed-это:|sed ':a;N;$!ba;s/\n/ /g' получил от здесь.

можно использовать grep:

grep -o "+\S\+" in.txt | tr '\n' ','

который находит строку, начинающуюся с +, за которым следует любая строка \S\+, затем преобразуйте новые символы строки в запятые. Это должно быть довольно быстро для больших файлов.

не видел это простое решение с awk

awk 'b{b=b","}{b=b}END{print b}' infile

С perl:

fg@erwin ~ $ perl -ne 'push @l, (split(/\s+/))[1]; END { print join(",", @l) . "\n" }' <<EOF
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)
EOF

+12.0,+15.5,+9.0,+13.5

вы также можете сделать это с двумя вызовами sed:

$ cat file.txt 
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)
$ sed 's/^[^:]*: *\([+0-9.]\+\) .*//' file.txt | sed -e :a -e '$!N; s/\n/,/; ta'
+12.0,+15.5,+9.0,+13.5

первый вызов sed удаляет неинтересные данные, а второй соединяет все строки.

вы также можете напечатать так:

просто awk: используя printf

bash-3.2$ cat sample.log
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

bash-3.2$ awk ' { if( != "") { if(NR==1) { printf  } else { printf ","  } } }' sample.log
+12.0,+15.5,+9.0,+13.5

другое решение Perl, похожее на awk Дана Фего:

perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/'

-a говорит perl разделить входную строку в массив @F, который индексируется, начиная с 0.

решение, написанное в чистом виде Bash:

#!/bin/bash

sometext="something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)"

a=()
while read -r a1 a2 a3; do
    # we can add some code here to check valid values or modify them
    a+=("${a2}")
done <<< "${sometext}"
# between parenthesis to modify IFS for the current statement only
(IFS=',' ; printf '%s: %s\n' "Result" "${a[*]}")

результат: +12.0,+15.5,+9.0,+13.5

Ну, самая сложная часть, вероятно, выбирает второй "столбец", так как я не знаю простого способа обработки нескольких пространств как одного. В остальном все просто. Использовать bash замен.

# cat bla.txt
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

# cat bla.sh
OLDIFS=$IFS
IFS=$'\n'
for i in $(cat bla.txt); do
  i=$(echo "$i" | awk '{print }')
  u="${u:+$u, }$i"
done
IFS=$OLDIFS
echo "$u"

# bash ./bla.sh
+12.0, +15.5, +9.0, +13.5