这是我的文件,其中包含两个列并用“\t”分隔
a HK97 family prohead protease [Lomovskayavirus C31]
b major capsid protein [Lomovskayavirus C31]
c gp12 [Lomovskayavirus C31]
d gp19 [Lomovskayavirus C31]
我希望 sed 能得到这样的文件
a Lomovskayavirus C31
b Lomovskayavirus C31
c Lomovskayavirus C31
d Lomovskayavirus C31
我已经尝试过该命令sed 's/.*[\(.*\)].*/\1/'
,它似乎没有用。那么我应该改变什么?谢谢。
答案1
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ awk -F '[][\t]' -v OFS='\t' '{print $1, $3}' file
a Lomovskayavirus C31
b Lomovskayavirus C31
c Lomovskayavirus C31
d Lomovskayavirus C31
答案2
您需要转义[
and ]
,因为它们具有特殊含义(要匹配的字符集合,我们稍后会需要),因此您得到:
sed 's/.*\[\(.*\)\].*/\1/'
但这也会删除第一列,所以尝试
sed 's/[ [:alnum:]]*\[\(.*\)\].*/\1/'
因此第一部分将捕获所有字母数字字符和空格,但不会捕获制表符,这只会删除制表符之后的所有内容。
答案3
使用乐(以前称为 Perl_6)
perl6 -ne 'given .split(/\s+/, 2) { put (.[0], .[1].match: / <?after "[" > .+ <?before "]" > /).join("\t") };'
或者
raku -ne 'given .split(/\s+/, 2) { put (.[0], .[1].comb: / "[" <(.+)> "]" /.[0]).join("\t") };'
Perl 系列语言是解决棘手的正则表达式问题的好方法。上面的两种策略可以混合搭配,也就是说您可以comb
使用前瞻/后瞻断言以及match
捕获标记。
上面第一个示例split
的每一行都有\s+
空白,但只分为2
两个片段。然后放置第一个元素,并在第二个元素中搜索match
模式<?after "[" > .+ <?before "]" >
。正则表达式原子 <?after … >
是 Raku 的正向前瞻断言,正<?before … >
则表达式原子是 Raku 的正向前瞻断言。由于这些断言是零宽度的,因此不需要捕获标记,并且可以直接输出匹配变量($/
或)。$<>
第二个示例也split
将每一行都放在\s+
空白处,同样只分成2
两个片段。再次放置第一个元素,并comb
遍历第二个元素以查找由和.+
包围的一个或多个字符。 Raku 的...捕获标记用于从输出中排除括号(在末尾添加索引以返回第二列中的第一个 ed 匹配项)。[
]
<(
)>
.[0]
comb
输入示例:
a HK97 family prohead protease [Lomovskayavirus C31]
b major capsid protein [Lomovskayavirus C31]
c gp12 [Lomovskayavirus C31]
d gp19 [Lomovskayavirus C31]
示例输出(上面的两个示例):
a Lomovskayavirus C31
b Lomovskayavirus C31
c Lomovskayavirus C31
d Lomovskayavirus C31
无论如何,如果您想放弃第一列,上面的代码可以简化为:
raku -ne 'put m/ <?after \[> .+ <?before \]> /;'
或者
raku -ne 'put .comb(/ \[ <(.+)> \] /).[0];'
答案4
使用sed
$ sed -E 's/( +)[^[]*\[([^]]*).*/\1\2/' input_file
a Lomovskayavirus C31
b Lomovskayavirus C31
c Lomovskayavirus C31
d Lomovskayavirus C31