Быстрый поиск структурированных текстовых данных из командной строки? - PullRequest
0 голосов
/ 03 июня 2018

Скажем, у меня есть предсказуемый текстовый документ, структурированный с некоторыми идентификаторами, называемыми X:, и известной комбинацией атрибутов, например, категория Y: с известным числом экземпляров (например, всегда только 1 Y: после каждого X: всерия):

  X:37
#  more data pertaining to item 37
  Y:BLUE
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"

Я хочу получить список идентификаторов предметов для всех синих вещей.Мне все равно, есть ли дублирующие идентификаторы или нет, только какие значения идентификаторов находятся в документе.Затем я хочу отсортировать список и сравнить со списком идентификаторов синей вещи из другого документа с структурированным текстом с точно такой же структурой («какие синие вещи являются общими для обеих документов?» «Какие синие вещи есть в документе 1, но не в документе 2».? ").

Я знаю, что могу grep для всех Y:BLUE строк довольно легко, но какие дополнительные команды мне нужны, чтобы найти непосредственно предшествующий X: для такого экземпляра и передать отсортированныйсписок результатов до diff?После AmiShell я не интенсивно использовал командную строку ... извините :-( Есть ли в Интернете кулинарная книга для таких случаев?

1 Ответ

0 голосов
/ 04 июня 2018

Давайте рассмотрим, что у вас есть следующие 2 входных документа:

$ more doc*
::::::::::::::
doc1
::::::::::::::
doc 1
  X:1
#  more data pertaining to item 37
#  more data pertaining to item 37
#  more data pertaining to item 37
  Y:BLUE
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
  X:2
#  more data pertaining to item 37
#  more data pertaining to item 37
  Y:BLUE
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
  X:3
#  more data pertaining to item 37
#  more data pertaining to item 37
  Y:RED
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
  X:4
#  more data pertaining to item 37
#  more data pertaining to item 37
  Y:BLUE
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
::::::::::::::
doc2
::::::::::::::
doc 2
  X:4
#  more data pertaining to item 37
#  more data pertaining to item 37
#  more data pertaining to item 37
  Y:BLUE
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
  X:3
#  more data pertaining to item 37
#  more data pertaining to item 37
  Y:BLUE
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
  X:2
#  more data pertaining to item 37
#  more data pertaining to item 37
  Y:RED
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
  X:1
#  more data pertaining to item 37
#  more data pertaining to item 37
  Y:BLUE
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"
# more serialized data items including exactly 1 occurrence of "Y:" per   preceding "X:"

Вы можете использовать следующую команду awk для каждого документа, чтобы получить идентификаторы:

$ awk -F':' '/X:[0-9]+$/{tmp=$2}/Y:BLUE$/{a[NR]=tmp}END{asort(a); for(i in a){print a[i]}}' doc1
1
2
4

$ awk -F':' '/X:[0-9]+$/{tmp=$2}/Y:BLUE$/{a[NR]=tmp}END{asort(a); for(i in a){print a[i]}}' doc2
1
3
4

Пояснения:

  • -F':' для определения : в качестве разделителя полей:
  • /X:[0-9]+$/{tmp=$2} сохранит в tmp переменную значения идентификаторов (Гипотеза, идентификаторы состоят только из цифр, и в строке больше ничего нет), если это не так, вы можете адаптировать регулярное выражение фильтрации /X:[0-9]+$/ в соответствии с вашими потребностями
  • /Y:BLUE$/{a[NR]=tmp}, когда мыдойдя до строки с шаблоном Y:BLUE (гипотеза: EOL сразу после BLUE), мы добавляем значение, сохраненное в tmp, в массив
  • , в конце обработки мы сортируем массив и печатаем его, обратите внимание, чтоВы изменили команду awk в awk -F':' '/X:[0-9]+$/{tmp=$2}/Y:BLUE$/{print tmp}' | sort -n

Затем вы можете объединить их следующим образом, чтобы найти различия в терминах синих идентификаторов между двумя документами:

$ diff <(awk -F':' '/X:[0-9]+$/{tmp=$2}/Y:BLUE$/{a[NR]=tmp}END{asort(a); for(i in a){print a[i]}}' doc1) <(awk -F':' '/X:[0-9]+$/{tmp=$2}/Y:BLUE$/{a[NR]=tmp}END{asort(a); for(i in a){print a[i]}}' doc2)                                                    
2c2
< 2
---
> 3

или найти общие между ними синие идентификаторы:

$ comm -1 -2 <(awk -F':' '/X:[0-9]+$/{tmp=$2}/Y:BLUE$/{a[NR]=tmp}END{asort(a); for(i in a){print a[i]}}' doc1) <(awk -F':' '/X:[
0-9]+$/{tmp=$2}/Y:BLUE$/{a[NR]=tmp}END{asort(a); for(i in a){print a[i]}}' doc2)                                              
1
4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...