在bash中解析出来

我的文件看起来像这样

// [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的数字行

好吧,在awk

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

考虑三种情况:

  • 一行只包含0和1( /^[01]+$/
  • 包含segsitespositions/(segsites|positions)/
  • 所有其他线路

在每种情况下,我们打印到不同的文件,然后继续下一行。 将"third-file""second-file""first-file"更改为适当的名称(保留引号)。

使用grep与PCRE [ -P ]和Dotall修饰符[ (?s) ]:

第一部分:

 $ 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 

第二部分:

 $ 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修饰符,使用此任何字符(包括换行符)都可以匹配.

  • (?=)是正向前瞻,代表我们的匹配

  • (?<)是正面的背后,代表我们比赛之前的东西