在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]+$/
) - 包含
segsites
或positions
:/(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修饰符,使用此任何字符(包括换行符)都可以匹配.
-
(?=)
是正向前瞻,代表我们的匹配 -
(?<)
是正面的背后,代表我们比赛之前的东西