Объединение столбцов в файл с помощью Awk

Входные данные:

ABC,SSSD,12345,NSS,12345,xxx,TS11 ,,,,,,TS21 ,,,,,,TS22 ,,,,,,BS26 ,,,,,,GPRS ABC,SSSD,12356,NSS,12356,xxx,TS11 ,,,,,,TS21 ,,,,,,TS22 ,,,,,,GPRS ,,,,,,BS26 

Вывод:

 ABC,SSSD,12345,NSS,12345,xxx,TS11|TS21|TS22|BS26|GPRS ABC,SSSD,12356,NSS,12356,xxx,TS11|TS21|TS22|GPRS|BS26 

Я уже пробовал написать сценарий ниже. Но это интенсивно работает:

 #!/bin/bash head -2 $1 | tail -1 >> $1"_output" sed '1,2d' $1 > temp$1.txt cp temp$1.txt $1 rm -f temp$1.txt while IFS='' read -r line || [[ -n $line ]]; do # echo "main line -- "$line # echo "prev line -- "$prevLine service=`echo $line | cut -d "," -f1` value=`echo $line | cut -d "," -f7` if [ "$service" != "" ] then if [ "$prevLine" != "" -a "$mvalue" != "" ] then echo $prevLine$mvalue >> $1"_output" fi prevLine=$line mvalue="" else #echo $value mvalue=$mvalue"|"$value #echo $mvalue fi done < "$1" echo $prevLine$mvalue >> $1"_output" 

Может ли кто-нибудь предложить лучший способ сделать это с помощью awk или любого лучшего метода?

  • среднее и стандартное отклонение от нескольких файлов
  • Как сделать замену на `$ 0`, но сохранить старое значение?
  • grep до соответствия скобкам
  • Как получить JSON STRING из данной строки
  • awk-манипуляция файлом fasta
  • Преобразование числовой строки из файла для вывода кода в оболочке
  • Автоматически загружать пользовательскую функцию при запуске с помощью awk?
  • Печать определенных полей каждой строки до тех пор, пока не будет обнаружен маркер, а затем напечатайте целые строки до конца файла
  • 5 Solutions collect form web for “Объединение столбцов в файл с помощью Awk”

    Если вы не слишком суетливы в отношении пробелов, вы делаете это с помощью двух правил awk:

      awk '$1 { printf "\n" $0 } !$1 { printf OFS $7 }' FS=, OFS='|' infile 

    Это оставляет пустую строку в начале вывода и пропускает один в конце. Чтобы исправить это, добавьте предложения if и END :

     awk '$1 { if(NR>1) printf "\n"; printf $0 } !$1 { printf OFS $7 } END { printf "\n" }' FS=, OFS='|' infile 

    Вывод:

     ABC,SSSD,12345,NSS,12345,xxx,TS11|TS21|TS22|BS26|GPRS ABC,SSSD,12356,NSS,12356,xxx,TS11|TS21|TS22|GPRS|BS26 

    Изменить – заметьте о% в $ 0

    Как заметил Гленн в комментариях, если ваши строки содержат % , безопаснее вызывать printf со строкой формата, например:

     awk '$1 { if(NR>1) printf "\n"; printf "%s", $0 } !$1 { printf OFS"%s", $7 } END { printf "\n" }' FS=, OFS='|' infile 

    Пока количество линий для слияния является постоянным awk просто можно решить, какой тип строки он имеет, глядя на номер строки:

     $ awk -F, '1==NR%5 { printf $0 "|";next } { printf $7 (NR%5?"|":"\n") }' DATA ABC,SSSD,12345,NSS,12345,xxx,TS11|TS21|TS22|BS26|GPRS ABC,SSSD,12356,NSS,12356,xxx,TS11|TS21|TS22|GPRS|BS26 

    если его всегда будет одинаковое количество строк (5), комбинация paste и sed может сделать:

     paste -d',' - - - - - <file | sed 's/,\{2,\}/|/g' 

    будет 1) paste 5 строк в один, используя в качестве разделителя, 2) заменить несколько (2 или более) запятых на одну трубу

    Другое sed :

     sed ':;N;s/\n,,,*/|/;t;P;D' file 

    Подобный ответ Тору, но сохраняет строку до ее завершения:

     awk -F, ' $1 != "" {if (record) print record; record = $0} $1 == "" {record = record "|" $NF} END {if (record) print record} ' file 

    Если вы хотите использовать bash, вы можете сделать

     lines=() while IFS= read -r line; do if [[ ${line:0:1} == "," ]]; then # the line starts a comma lines[-1]+="|${line##*,}" # strip the commas and append to # the last element of the array else lines+=("$line") # append the line to the array fi done <<"$1" printf "%s\n" "${lines[@]}" 
     ABC,SSSD,12345,NSS,12345,xxx,TS11|TS21|TS22|BS26|GPRS ABC,SSSD,12356,NSS,12356,xxx,TS11|TS21|TS22|GPRS|BS26 
    Linux и Unix - лучшая ОС в мире.