Сопоставить символ и извлечь данные из нижних строк - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть большой файл с разделителями табуляции, и его часть выглядит так:

25      M   X   A   A   X   S
25_a    M   K   A   A   R   S
25_b    M   A   A   A   V   S
31      M   A   A   A   V   S
31_a    M   A   A   A   V   S
31_b    M   A   A   A   V   S

Я пытаюсь играть с тремя строками одновременно, первая строка содержит последовательность ссылок (фактическая последовательность ) тогда как следующие две строки отражают его варианты. Я пытаюсь сделать две вещи:

Во-первых, из первого ряда (контрольная строка (25)) я пытаюсь идентифицировать (сопоставить) символ (X) и пытаюсь сохранить только соответствующий символы в двух нижних строках (25_a, 25_b), чтобы получить что-то вроде показанного ниже,

25      M   X   A   A   X   S
25_a        K           R   
25_b        A           V   

Во-вторых, если в строке ссылки (31) нет (X), то удалите соответствующие две строки (31_a, 31_b), чтобы получить что-то вроде этого:

31      M   A   A   A   V   S

И окончательный вывод должен быть похож на

25      M   X   A   A   X   S
25_a        K           R   
25_b        A           V   
31      M   A   A   A   V   S

Я знаю, что мы можем удалить после указанного c символа с помощью команды sed но я изо всех сил пытаюсь получить желаемый результат. Любая помощь будет высоко оценена

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

Это может сработать для вас (GNU sed):

sed -E 'N;N;/^.._./!{/^\S+\s.*X/!{P;d};s/^(\S+\s*)(.*\n\S+\s*)(.*\n\S+\s*)/\1\n\2\n\3\n/;:a;/\n\n/{s/\n+/\n/g;s/.$//;b};s/\n([X\t])(.*\n.*)\n(.)(.*\n.*)\n(.)/\1\n\2\3\n\4\5\n/;ta;s/\n(.)(.*\n.*)\n(.)(.*\n.*)\n(.)/\1\n\2\n\4\n/;ta}' file

Добавить следующие две строки к текущей строке.

Если контрольная строка не содержит X, выведите в первой строке и удалите оставшиеся две.

В противном случае: вставьте три символа новой строки, по одной после клавиш каждой из трех строк в пространстве образца.

Используя al oop, проверьте символ, следующий за первой вставленной новой строкой, должен быть либо X, либо табуляцией, и, если это так, переместите новую строку над ней и сделайте то же самое с двумя другими строками.

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

Повторяйте, пока не обработается вся первая строка.

В конце строки При обработке вставленные символы новой строки удаляются, а результат печатается.

0 голосов
/ 02 апреля 2020

Учитывая этот ввод (я использовал здесь пробелы, чтобы сделать его красивее, но это должны быть вкладки)

25      a   X   X   q   X   c
25_a    b   g   l   r   w   d
25_b    c   h   m   s   y   e
31      d   i   0   0   z   f
41      d   i   X   X   z   f
41_a    e   j   o   u   a   g
41_b    f   k   p   v   b   h
41_c    f   k   p   v   b   h
47      d   i   0   0   z   f
47_a    e   j   o   u   a   g
47_b    f   k   p   v   b   h

и этот желаемый вывод (пробелы должны быть табуляции)

25      a   X   X   q   X   c
25_a    b           r       d
25_b    c           s       e
31      d   i   0   0   z   f
41      d   i   X   X   z   f
41_a    e   j           a   g
41_b    f   k           b   h
41_c    f   k           b   h
47      d   i   0   0   z   f

Следующий скрипт выполняет свою работу:

#!/usr/bin/env -S sed -Ef
/^[0-9]+\t/!d
/^[0-9]+\t.*X/{
  :next
  N
  /.*\n[0-9]+_[^\n]*$/!bprint
  :mark
  s/^([^\n]*)\t([^\t\x0][^\n]*\n)/\1\x0\2/
  s/^(.*)\n(.*)\t([^\t\x0])([^\n]*)$/\1\n\2\x0\3\4/
  tmark
  :clean
  /^([^\x0]*)\x0[^X]/s/^([^\x0]*)\x0(.*)\n([^\x0]*)\x0(.*)$/\1\t\2\n\3\t\4/
  /^([^\x0]*)\x0X/s/^([^\x0]*)\x0X(.*)\n([^\x0]*)\x0.(.*)$/\1\tX\2\n\3\t\4/
  tclean
  bnext
  :print
  h
  s/(.*)\n.*/\1/
  p
  x
  s/.*\n(.*)/\1/
  /X/bnext
}

Этот скрипт является более общим, чем необходимо, так как он работает с любым количеством строк или столбцов. Я также проверил с небольшим патроном вашего ввода, содержащего значительное количество X es (столбцы с 240-го по 260-е), и он работает.

С другой стороны, он очень медленный. Я мог бы упростить это, считая, что линии всегда в группах по 3; это, конечно, уменьшит сложность сценария.

Но было забавно сделать это более общим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...