Как распечатать данные в заказе, используя awk? - PullRequest
0 голосов
/ 25 октября 2019
ABC has x types:
x.x  used by xyzzy
x.y.z used by pqr
a.b.c.d used by mno   
PQR has x types:
x.x  used by xyzzy
x.y.z used by pqr   
XYZ has x types:
x.x  used by xyzzy
p.q.r used by pqr

Критерии для получения ожидаемого результата -

  • Прочитайте первый столбец строки, где находится "has x types", поместите его в переменную и переместитеперейти к следующей строке и получить первый столбец следующей строки в другой переменной и перейти к следующей строке.
  • Если эта строка находится чуть выше строки, содержащей "has x types", то выведите первую и вторую переменную в разделенном каналеформат.

Ожидаемый вывод -

ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r

Я пробовал это -

awk '$0 ~ /has/ {p=$1}; q=$1; {print p,q}' k
ABC has x types:
ABC ABC
x.x  used by xyzzy
ABC x.x
x.y.z used by pqr
ABC x.y.z
a.b.c.d used by mno
ABC a.b.c.d
PQR has x types:
PQR PQR
x.x  used by xyzzy
PQR x.x
x.y.z used by pqr
PQR x.y.z
XYZ has x types:
XYZ XYZ
x.x  used by xyzzy
XYZ x.x
p.q.r used by pqr
XYZ p.q.r

Ответы [ 6 ]

2 голосов
/ 25 октября 2019

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

awk '
BEGIN{
  OFS=" | "
}
/has/{
  if(val && prev){
     print val,prev
     prev=val=""
  }
  val=$1
  next
}
{
  prev=$1
}
END{
  if(val && prev){
      print val,prev
  }
}
'  Input_file

Вывод будет следующим.

ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r


РЕДАКТИРОВАТЬ: Добавление решения GNU awk. Протестировано и написано в GNU awk. Также хочу упомянуть, что это может быть немного медленным для файлов большого размера, так как он будет читать весь файл одной строкой.

awk -v RS="" -v FS="\n" '
BEGIN{
  OFS=" | "
}
{
  for(i=1;i<=NF;i++){
    if($i~/has/){
      if(val){
        split(val,array1," ")
        split($(i-1),array2," ")
        print array1[1],array2[1]
        val=""
      }
      val=$i
    }
  }
  delete array1
  delete array2
}
'   Input_file
1 голос
/ 25 октября 2019

Вот еще один awk скрипт с пояснениями:

scirpt.awk

BEGIN {OFS = " | "}  # assign output separator to " | "
/ has / { # on lines with "has"
    if (key) print key, val; # print the previous key | value if key exist
    key = $1;  # capture the recent key from 1st input field
}
{ # on any line 
    val = $1; # capture the recent value from 1st input field
}
END {print key, val} # output the last key | value pair

input.txt

ABC has x types:
x.x  used by xyzzy
x.y.z used by pqr
a.b.c.d used by mno   
PQR has x types:
x.x  used by xyzzy
x.y.z used by pqr   
XYZ has x types:
x.x  used by xyzzy
p.q.r used by pqr

работает:

awk -f script.awk input.txt

вывод:

ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r
1 голос
/ 25 октября 2019
$ awk -v OFS=' | ' '/has/{if (NR>1) print key, prev; key=$1} {prev=$1} END{ print key, prev }' file
ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r
1 голос
/ 25 октября 2019

Ну, потому что вы можете сделать это с одним большим седом,

cat file | tr '\n' '@' | sed 's/@$//;s/ *used by[^@]*//g;s/@\([^@]*has x types:\)/\n\1/g;s/ *has[^\n]*@/ | /g'
1 голос
/ 25 октября 2019

Третий вариант в awk может быть:

awk '$1~/^[A-Z]+$/ {lbl=$1}; {a[lbl]=$1}; END {for(i in a) print i,"|",a[i]}' file

Пояснение

Приведенная выше команда awk имеет 3 правила:

  • $1~/^[A-Z]+$/ {lbl=$1}, если первое поле все в верхнем регистре, сохраните файл в lbl (для метки). Это выполняется только в том случае, если все поле 1 имеет верхний регистр;
  • {a[lbl]=$1} устанавливает массив a[lbl] равным первому полю (выполняется для всех записей);и
  • END {for(i in a) print i,"|",a[i]} в конце обработки всех записей циклически перебирайте все элементы в вашем массиве a, выводя последнее сохраненное значение для метки.

По сути, выпросто сохраняйте первое поле в a[lbl], где lbl - это последнее из всех заглавных букв. Результат: a[lbl] содержит последнее первое поле, видимое под каждой меткой.

Пример Использование / Вывод

С вашими данными в file, затем

$ awk '$1~/^[A-Z]+$/{lbl=$1}; {a[lbl]=$1}; END { for(i in a) print i,"|",a[i] }' file
ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r
0 голосов
/ 25 октября 2019

Я также выясняю это с помощью массива -

awk '/has/ {p=$1} {a[p]=$1} END {for (p in a) print p "|" a[p]}' f
XYZ|p.q.r
PQR|x.y.z
ABC|a.b.c.d
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...