Это не особенно легко, но и не невероятно сложно. Вся интересная информация находится в полях, разделенных двоеточиями, поэтому одна часть состоит в том, чтобы awk
разделить строку ввода на поля на основе двоеточий (-F:
). Затем необходимо распознавать номера групп, членов группы, ранги участников и идентификаторы участников. Любая строка без соответствующей информации просто игнорируется. Поиск значений поля можно выполнить, просматривая поля в поисках совпадений с ключевым словом и возвращая поле после него в качестве значения. В приведенном ниже коде эту работу выполняет функция extractor
. Также необходимо отслеживать, сколько раз был напечатан номер группы. В конце ввода или при распознавании нового номера группы, если старый номер группы был напечатан ноль раз, необходимо распечатать информацию о группе. Функция print_member
печатает элемент; это экономит запись оператора printf
3 раза.
awk -F: '
function extractor(tag, i)
{
for (i = 1; i < NF; i++)
if ($i ~ tag)
return $(i + 1)
return ""
}
function print_member()
{
printf "%s,%s,%s,%s\n", groupnumber, groupmember, groupmemberid, memberrank
}
/GROUPNUMBER:[0-9]+/ {
if (groupnumber != "" && groupcount == 0)
print_member()
groupnumber = extractor("GROUPNUMBER")
groupmember = ""
memberrank = ""
groupmemberid = ""
groupcount = 0
}
/GROUPMEMBER:[^:]+:MEMBERRANK:[0-9]+/ {
groupmember = extractor("GROUPMEMBER")
memberrank = extractor("MEMBERRANK")
}
/GROUPMEMBERID:[0-9]+/ {
groupmemberid = extractor("GROUPMEMBERID")
print_member()
groupcount++
}
END {
if (groupcount == 0)
print_member()
}' data
Учитывая файл данных в вопросе (имя data
), вывод:
111222,Joe,1234,1
111222,Mike,2234,1
111222,Sue,3234,89
111222,John,4234,323
333444,Frank,5234,4
333444,Laurie,6234,4
88888,,,
Кажется, это необходимый результат. Теперь рассмотрим измененный входной файл (с многочисленными дополнениями) следующим образом:
loremipsum: loremipsum?# loremipsum/123: loremipsumxx GROUPNUMBER:111222:hydrangea
loremipsum123:loremispum loremipsumxxxx
GROUPMEMBER:Joe:MEMBERRANK:1:orchid
GROUPMEMBERID:1234
GROUPMEMBER:Mike:piscatore:MEMBERRANK:1
GROUPMEMBERID:2234
loremipsum14e3:loremispum loremipsumxxxx
loremipsum1eer534:loremispum loremipsumxxfgt
GROUPMEMBER:Sue:MEMBERRANK:89
GROUPMEMBERID:3234
GROUPMEMBER:John:MEMBERRANK:323
GROUPMEMBERID:4234:loremipsumaaa_loremipsum
loremipsum: loremipsum..<?# loremipsum/123: loremipsumxx GROUPNUMBER:333444
loremipsum123:loremispum loremipsumxxxx
GROUPMEMBER:Frank:MEMBERRANK:4
GROUPMEMBERID:5234
GROUPMEMBER:Laurie:MEMBERRANK:4
GROUPMEMBERID:6234
loremipsum: loremipsum..<?# loremipsum/123: loremipsumxx GROUPNUMBER:88888
loremipsum123:loremispum loremipsumxxxx
loremipsum: loremipsum..<?# loremipsum/123: loremipsumxx GROUPNUMBER:222444
loremipsum123:loremispum loremipsumxxxx
GROUPMEMBER:Helen Mary Ann:MEMBERRANK:1
loremipsum: loremipsum..<?# loremipsum/123: loremipsumxx GROUPNUMBER:222555
loremipsum123:loremispum loremipsumxxxx
loremipsum123:loremispum loremipsumxxxx
Вывод сейчас:
111222,Joe,1234,1
111222,Joe,2234,1
111222,Sue,3234,89
111222,John,4234,323
333444,Frank,5234,4
333444,Laurie,6234,4
88888,,,
222444,Helen Mary Ann,,1
222555,,,
Это выглядит разумно. Пробелы в имени Хелен Мэри Энн не имеют значения; для нее не было членского удостоверения. Группа посередине без информации тоже отображается правильно.
Очевидно, вы можете преобразовать его в пригодный для использования сценарий оболочки, поместив его в файл и заменив data
на "$@"
, чтобы он обрабатывал имена файлов, указанные в командной строке, или считывал стандартный ввод, если таких имен нет.
Как отмечено в комментариях, приведенный выше код предполагает, что поля GROUPMEMBER и MEMBERRANK будут следовать друг за другом в строке без каких-либо случайных полей типа «ipsum lorem» между ними. Если на самом деле между ними может быть поле «ipsum lorem» (я использовал piscatore
во втором наборе данных), то сценарий необходимо пересмотреть, чтобы идентифицировать GROUPMEMBER и MEMBERRANK по отдельности. Это имеет дополнительное преимущество, если входные данные содержат:
ipsum lorem:MEMBERRANK:1:ipsum lorem:GROUPMEMBER:Hailey:ipsum lorem
or
ipsum lorem:MEMBERRANK:110:ipsum lorem
hallucination:GROUPMEMBER:Julian:doldrums
тогда он будет точно распознавать информацию (с линиями в любом порядке во втором примере). GROUPMEMBERID должен быть последним из трех элементов для каждого члена с заданным GROUPNUMBER.
awk -F: '
function extractor(tag, i)
{
for (i = 1; i < NF; i++)
if ($i ~ tag)
return $(i + 1)
return ""
}
function print_member()
{
printf "%s,%s,%s,%s\n", groupnumber, groupmember, groupmemberid, memberrank
}
/GROUPNUMBER:[0-9]+/ {
if (groupnumber != "" && groupcount == 0)
print_member()
groupnumber = extractor("GROUPNUMBER")
groupmember = ""
memberrank = ""
groupmemberid = ""
groupcount = 0
}
/GROUPMEMBER:[^:]+/ {
groupmember = extractor("GROUPMEMBER")
}
/MEMBERRANK:[0-9]+/ {
memberrank = extractor("MEMBERRANK")
}
/GROUPMEMBERID:[0-9]+/ {
groupmemberid = extractor("GROUPMEMBERID")
print_member()
groupcount++
}
END {
if (groupcount == 0)
print_member()
}' data
Вывод сейчас:
111222,Joe,1234,1
111222,Mike,2234,1
111222,Sue,3234,89
111222,John,4234,323
333444,Frank,5234,4
333444,Laurie,6234,4
88888,,,
222444,Helen Mary Ann,,1
222555,,,
person
Jonathan Leffler
schedule
12.12.2019
which have served me well so many times before
На этом форуме мы призываем других сообщать о том, что они пробовали. Пожалуйста, опубликуйте, что вы пробовали, и покажите, что мешает вам написать это. В чем именно заключается ваш вопрос? Хотя я считаю, что это можно сделать в sed, решение на awk было бы намного проще и читабельнее. - person KamilCuk   schedule 12.12.2019GROUPNUMBER:111222
и т. д. строки из всего остального текста, который вы loremipsum- изд. Например, это единственные строки в вашем вводе, которые являютсяall upper case then colon then digits
? - person Ed Morton   schedule 12.12.2019