我有一个看起来像的文件:
uniprotkb:Q9VNB0|intact:EBI-102551 uniprotkb:A1ZBG6|intact:EBI-195768
uniprotkb:P91682|intact:EBI-142245 uniprotkb:Q24117|intact:EBI-156442
uniprotkb:P92177-3|intact:EBI-204491 uniprotkb:Q9VDK2|intact:EBI-87444
我希望在:
和|
分隔符之间提取字符串,输出应为:
Q9VNB0 A1ZBG6
P91682 Q24117
P92177-3 Q9VDK2
选项卡在两列之间分隔。 我在unix中写了一个perl命令:
perl -l -ne '/:([^|]*)?[^:]*:([^|]*)/ and print($1,"\t",$2)' <file>
我得到的输出是:
Q9VNB0 EBI-102551 uniprotkb:A1ZBG6
P91682 EBI-142245 uniprotkb:Q24117
P92177-3 EBI-204491 uniprotkb:Q9VDK2
我想知道我做错了什么,我该如何解决问题。 我不想使用分割功能。
谢谢,
汤姆。
答案 0 :(得分:1)
你提供的表达方式过于贪婪,因此消耗的字符比你想要的多。以下表达式适用于您的示例数据集:
perl -l -ne '/:([^|]*)\|.*:([^|]*)\|/ and print($1,"\t",$2)'
它使用":"
和"|"
对之间的明确匹配来锚定搜索。如果您的数据不完全匹配,应该忽略输入行,但我没有对此进行测试。也就是说,这个正则表达式假定每行":"
和"|"
之间恰好有两个条目。
答案 1 :(得分:0)
请尝试m/: ( [^:|]+ ) \| .+ : ( [^:|]+ ) \| /x
。
答案 2 :(得分:0)
修复可能是在第一个字符串和第二个字符串之间使用greeding表达式。使用.*
直到结束并开始回溯搜索最后一个冒号后跟管道。
perl -l -ne '/:([^|]*).*:([^|]*)\|/ and print($1,"\t",$2)' <file>
输出:
Q9VNB0 A1ZBG6
P91682 Q24117
P92177-3 Q9VDK2
答案 3 :(得分:0)
答案 4 :(得分:0)
你指定它的方式,它必须匹配这种方式。你想要一个冒号 其次是任意数量的非管道,其次是任意数量的非冒号。
single colon -> :
non-pipe -> Q9VNB0
non-colon -> |intact
colon -> :
non-pipe -> EBI-102551 uniprotkb:A1ZBG6
相反,我在合同结束时建立了一个空间,并要求我的所有模式开始 带冒号,以管道结尾,由非空格/非管道字符组成。
perl -M5.010 -lne 'say join( "\t", m/[:]([^\s|]+)[|]/g )';
答案 5 :(得分:0)
perl -nle'print "$1\t$2" if /:([^|]*)\S*\s[^:]*:([^|]*)/'
或者使用5.10 +:
perl -nE'say "$1\t$2" if /:([^|]*)\S*\s[^:]*:([^|]*)/'
说明:
: Matches the start of the first "word".
([^|]*) Matches the desired part of the first "word".
\S* Matches the end of the first "word".
\s+ Matches the "word" separator.
[^:]*: Matches the start of the second "word".
([^|]*) Matches the desired part of the second "word".
这不是最短的答案(虽然它很接近),因为每个部分都完全独立于其他部分。这使其更加健壮,不易出错,并且更易于维护。
答案 6 :(得分:0)
为什么不想使用split
功能。从表面上看,这可以通过编写
my @fields = map /:([^|]+)/, split
我不确定你的正则表达式是如何工作的。使用/x
修饰符允许非重要的空格,它看起来像这样
/ : ([^|]*)? [^:]* : ([^|]*) /x
找到冒号并可选地捕获尽可能多的非管道字符。然后跳过尽可能多的非冒号字符到下一个冒号。然后捕获零asm尽可能多的非管道字符。因为所有匹配都是贪婪的,所以只要字符与字符类匹配,就允许其中任何一个匹配消耗所有其余字符串。请注意,指示可选序列的?
将首先匹配所有序列,并且只有在无法使其余模式匹配时才会跳过序列的选项
很难从您的示例中判断字段的准确标准,但此代码应该可以解决问题。它找到的字符序列既不是冒号也不是管道,前面有冒号,以管道
结尾use strict;
use warnings;
while (<DATA>) {
my @fields = /:([^:|]+)\|/g;
print join("\t", @fields), "\n";
}
__DATA__
uniprotkb:Q9VNB0|intact:EBI-102551 uniprotkb:A1ZBG6|intact:EBI-195768
uniprotkb:P91682|intact:EBI-142245 uniprotkb:Q24117|intact:EBI-156442
uniprotkb:P92177-3|intact:EBI-204491 uniprotkb:Q9VDK2|intact:EBI-87444
<强>输出强>
Q9VNB0 A1ZBG6
P91682 Q24117
P92177-3 Q9VDK2