парсинг в ударе

мой файл похож на это

//
[297]((((21:0.125204,20:0.125204):0.00994299,(28:0.0790047,(7:0.0146105,5:0.0146105):0.0643943):0.0561423):0
segsites:
positions: 1 2 4 6 9 10 45 67 78 89 
01010101010101010101010101011111010101

Я должен был бы проанализировать его в три различных файла

//
[297]((((21:0.125204,20:0.125204):0.00994299,(28:0.0790047,(7:0.0146105,5:0.0146105):0.0643943):0.0561423):0

затем

 segsites:
    positions: 1 2 4 6 9 10 45 67 78 89 

 01010101010101010101010101011111010101

проблема состоит в том, что нет постоянного числа строк, запускающихся со скобок и так далее. заключительная строка могла запуститься или с 0 или с 1, и это - проблема, поскольку я не знаю, как сказать grep искать или 0 или 1. Мне было бы нужно к grep для []. затем segsites и строка, ниже которой включает pos и затем числовую строку с 01

1
задан 21 May 2015 в 23:08

2 ответа

Ну, в awk:

awk '/^[01]+$/ {print > "third-file"; next} 
 /(segsites|positions)/ {print > "second-file"; next} 
 {print > "first-file"}' input-file

Рассмотрение трех случаев:

  • строка А, содержащая только 0s и 1 с (/^[01]+$/)
  • строка А, содержащая или segsites или positions: /(segsites|positions)/
  • Все другие строки

В каждом случае, мы печатаем в различный файл и продолжаем двигаться к следующей строке. Изменение "third-file", "second-file", "first-file" для адаптации имен (сохраняют кавычки).

3
ответ дан 3 December 2019 в 07:01

Используя grep с PCRE [-P] и модификатор Dotall [(?s)]:

1-я часть:

$ grep -Poz "(?s)^.*?(?=\nsegsites:)" file.txt 
//
[297]((((21:0.125204,20:0.125204):0.00994299,(28:0.0790047,(7:0.0146105,5:0.0146105):0.0643943):0.0561423):0

2-я часть:

$ grep -Poz "(?s)segsites.*?(?=\n[10]+$)" file.txt 
segsites:
positions: 1 2 4 6 9 10 45 67 78 89 

В случае третьей части только grep сделает (если у Вас будет всего одна строка):

$ grep -E "^[01]+$" file.txt
01010101010101010101010101011111010101

Если Вы не уверены (единственные/несколько строки):

$ grep -Poz "(?<=\n)(?:[10]|\n)*(?=\n$)" file.txt 
010101010101010101010101010111110101011
01010101010101010101010101011111010101010

$ grep -Poz "(?<=\n)(?:[10]|\n)*(?=\n$)" file.txt 
010101010101010101010101010111110101011

Объяснения:

  • grep -P представляет PCRE (Perl Совместимые Регулярные выражения)

  • grep -o выберет только подобранную часть

  • grep -z заставит строки быть разделенными ASCII NUL вместо новых строк

  • (?s) назван модификатором Dotall, использование этого любого символа (включая разрывы строки) может быть подобрано .

  • (?=) Положительное предвидение, представляет то, что следует за нашим соответствием

  • (?<) Положительный lookbehind, представляет то, что предшествует нашему соответствию

1
ответ дан 3 December 2019 в 07:01

Другие вопросы по тегам:

Похожие вопросы: