Команда awk для разбора файла, разделенного новыми строками - PullRequest
2 голосов
/ 05 февраля 2020

Мой входной файл выглядит следующим образом:

OS ABI

   UNIX - System V

CPU Class

   64-bit

Persistence (user)

   No

File type 

   ELF 32-bit MSB executable, PowerPC or cisco 4500, version 
   (SYSV),statically linked, not   stripped,32-bit MSB executable, 
   PowerPC or cisco 4500, version (SYSV),statically linked, not stripped

CPU Type

  PowerPC

Я хочу выводить как:

OS ABI UNIX - System V
CPU CLASS 64-bit
Persistence (user) No
File Type ELF 32-bit MSB executable, PowerPC or cisco 4500, version (SYSV),statically linked, not   stripped,32-bit MSB executable, PowerPC or cisco 4500, version (SYSV),statically linked, not stripped 
CPU Type PowerPC

Пожалуйста, предложите скрипт / команду, используя awk, которая может выводить желаемый результат? Проблема возникает, когда мы должны проанализировать несколько строк, как показано в поле 5. Я также wi sh для подсчета количества строк в каждом поле. Например: поле 1 имеет одну строку, поле 5 имеет 2 et c.

Ответы [ 4 ]

3 голосов
/ 05 февраля 2020
$ awk -v RS= 'NR%2{p=$0; next} {$0=p $0; $1=$1} 1' file
OS ABI UNIX - System V
CPU Class 64-bit
Persistence (user) No
File type ELF 32-bit MSB executable, PowerPC or cisco 4500, version (SYSV),statically linked, not stripped,32-bit MSB executable, PowerPC or cisco 4500, version (SYSV),statically linked, not stripped
CPU Type PowerPC
3 голосов
/ 05 февраля 2020

Это сделает за вас:

awk 'BEGIN{RS=""}
     !/^[[:blank:]]/{printf "%s" OFS, $0; next}
     { gsub(/(^|\n)[[:blank:]]+/,OFS) }1' file

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

3 голосов
/ 05 февраля 2020

Другой вариант awk:

awk '/^[^ \t]/{if (p != "") print p; p=$0} 
/^[ \t]/{sub(/^[ \t]+/, ""); p = p " " $0} END{print p}' file

OS ABI UNIX - System V
CPU Class 64-bit
Persistence (user) No
File type  ELF 32-bit MSB executable, PowerPC or cisco 4500, version  (SYSV),statically linked, not   stripped,32-bit MSB executable,  PowerPC or cisco 4500, version (SYSV),statically linked, not stripped
CPU Type PowerPC

Или, если вы можете использовать perl, используйте этот однострочный:

perl -0777 -pe 's/(?:\h*\R+)+\h+/ /g; s/\R(?:\h*\R)+/\n/g' file
3 голосов
/ 05 февраля 2020

РЕДАКТИРОВАТЬ: Поскольку OP изменил файл Input_file, добавив еще одно решение здесь в соответствии с новыми образцами.

awk -v RS="" -v FS="\n" '
{
  gsub(/\n+/,OFS)
}
FNR%2==0{
  print value,$0
  next
}
{
  value=$0
}
'  Input_file

Объяснение: Добавление подробного пояснения к вышеуказанному коду.

awk -v RS="" -v FS="\n" '     ##Setting RS(record separator) as NULL and setting FS(field separator) as new line.
{
  gsub(/\n+/,OFS)             ##Globally substituting one or more lines occurrence with space here.
}
FNR%2==0{                     ##Checking condition if line number is even then do following.
  print value,$0              ##Printing value and current line here.
  next                        ##next will skip all further statements from here.
}
{
  value=$0                    ##Assigning current line value to variable value here.
}
' Input_file                  ##Mentioning Input_file name here.


Не могли бы вы попробовать, написано и протестировано с предоставленными образцами.

awk '
NF && /^Field/{
  if(field_value && value){
    print field_value,value
  }
  value=""
  field_value=$0
  next
}
NF{
  value=(value?value OFS:"")$0
}
END{
  if(field_value && value){
    print field_value,value
  }
}
'  Input_file
...