Извлечь несколько строк с помощью awk - PullRequest
2 голосов
/ 10 февраля 2020

Я пытаюсь извлечь две строки из каждой строки, некоторые строки не имеют ни одной строки, некоторые строки имеют одну строку.

Мой ввод input.txt:

ID=MD001;refer=init;loc=tap2
ID=MD002;Name=Jam;refer=init;loc=tap2
ID=MD003;Name=Jane;Value=vip;refer=init;loc=tap2
ID=MD008;Name=George;product=car;vall=some;Value=vim;refer=init;loc=tap2
ID=MD0010;product=cars;Value=vip4;refer=init;loc=tap2
ID=MD0018;product=cars;
...

Я хочу сопоставить строку «Имя» или «Значение» и вывести их в виде:

ID=MD002 Name=Jam
ID=MD003 Name=Jane Value=vip
ID=MD008 Name=George Value=vim
ID=MD0010 Value=vip4

Я пытался:

head input.txt | awk '$1 ~ /Name|Value/ {match($1, /(ID=*);.*(Name*);.*(Value.*)/, name); print name[1] name[2] name[3]}'

Но это действительно печатало что-нибудь. Спасибо за помощь.

Ответы [ 5 ]

2 голосов
/ 10 февраля 2020

Не могли бы вы попробовать следующее.

awk '
BEGIN{
  FS=";"
}  
  {
  for(i=2;i<=NF;i++){
    if($i~/^Name|^Value/){
      val=(val?val OFS:"")$i
    }
  }
  if(val){
    print $1,val;
  }
  val=""
}
'  Input_file

Вывод будет следующим для показанных образцов.

ID=MD002 Name=Jam
ID=MD003 Name=Jane Value=vip
ID=MD008 Name=George Value=vim
ID=MD0010 Value=vip4
1 голос
/ 10 февраля 2020

другой аналог awk

$ awk -F\; -v p='(Name|Value)=' '
       $0~p {printf "%s ", $1; 
             for(i=2; i<=NF; i++) if($i~p) printf "%s ", $i; 
             print ""}' file

ID=MD002 Name=Jam
ID=MD003 Name=Jane Value=vip
ID=MD008 Name=George Value=vim
ID=MD0010 Value=vip4
1 голос
/ 10 февраля 2020

Начните с этого:

$ cat tst.awk
BEGIN { FS="[=;]" }
{
    delete f
    for (i=1; i<NF; i+=2) {
        f[$i] = $i "=" $(i+1)
    }
    print f["ID"], f["Name"], f["Value"]
}

$ awk -f tst.awk file
ID=MD001
ID=MD002 Name=Jam
ID=MD003 Name=Jane Value=vip
ID=MD008 Name=George Value=vim
ID=MD0010  Value=vip4
ID=MD0018

, а затем настройте для соответствия (используя оператор in для проверки наличия), если вы хотите не печатать строки и / или не печатать пропущенные значения:

$ cat tst.awk
BEGIN { FS="[=;]" }
{
    delete f
    for (i=1; i<NF; i+=2) {
        f[$i] = $i "=" $(i+1)
    }

    hit = 0
    out = f["ID"]
    out = out val("Name")
    out = out val("Value")
}
hit { print out }

function val(tag) {
    if (tag in f) {
        hit = 1
        return (OFS f[tag])
    }
}

$ awk -f tst.awk file
ID=MD002 Name=Jam
ID=MD003 Name=Jane Value=vip
ID=MD008 Name=George Value=vim
ID=MD0010 Value=vip4
0 голосов
/ 11 февраля 2020

Это может быть полезно для функции FPAT в awk, где поля определяются их содержимым, а не их разделителями. См. https://www.gnu.org/software/gawk/manual/html_node/Splitting-By-Content.html

awk '
    BEGIN {
            FPAT = "(ID=[^;\v]+)|(Name=[^;\v]+)|(Value=[^;\v]+)"
    }

    NF>1 {
            # Only prints lines that have Name and/or Value
            for (i=1; i<NF; i++) {
                    printf $i " "
            }
            print $NF
    }
' file

FPAT определяет 3 возможных поля. Первый, (ID=[^;\v]+), означает, что он должен начинаться с ID = и сопровождаться хотя бы одним символом, который не является ни точкой с запятой, ни вертикальным пробелом. Следующие два, (Name=[^;\v]+) и (Value=[^;\v]+), аналогично означают Имя = или Значение =, за которым следует хотя бы один символ, который не является ни точкой с запятой, ни вертикальным пробелом.

0 голосов
/ 11 февраля 2020

А еще другое:

$ awk -F\; '{                                 # set the delim
    for(i=2;i<=NF;i++)                        # looping from the 2nd field
        if($i~/^(Name|Value)/) {              # looking for keywords and if found
           for(i=1;i<=NF;i++)                 # restart loop from beginning
               if($i~/^(Name|Value)/||i==1)   # outputing first field and matches
                   printf "%s ",$i
           print ""                           # newline in the end
           # next                             # breaking from the 1st loop not needed
        }
}' file

Вывод:

ID=MD002 Name=Jam 
ID=MD003 Name=Jane Value=vip 
ID=MD008 Name=George Value=vim 
ID=MD0010 Value=vip4 
...