我有一个包含多行的 .txt 文件,其中提供氨基酸和残基数据。数据如下:
ARG262-Side ASP368-Side 140,83%
ARG95-Side GLU107-Side 103,73%
ARG474-Side VAL468-Main 94,93%
PHE169-Main ALA190-Main 94,63%
THR205-Side ASP203-Side 94,07%
ILE299-Main LYS249-Main 94%
LEU354-Main LYS365-Main 93,6%
ARG346-Side GLU263-Side 93,57%
LEU301-Main ALA247-Main 93,43%
ALA190-Main PHE169-Main 93,37%
SER252-Side ASP296-Side 93,1%
TYR424-Side ASN446-Main 93%
我可以粗略地说,数字表示残基,字母表示氨基酸。因此,在每行的第一和第二字段中,前面的部分-
由氨基酸标识符和残基值组成。我只想打印可见残基值位于特定范围内的行,无论氨基酸如何,也无论第一个或第二个字段是否符合标准。
例如,从上面的输入文件中,我想提取仅包含之间残基的数据300-425。在这种情况下,我的输出应该如下所示:
ARG262-Side ASP368-Side 140,83%
LEU354-Main LYS365-Main 93,6%
ARG346-Side GLU263-Side 93,57%
LEU301-Main ALA247-Main 93,43%
TYR424-Side ASN446-Main 93%
我尝试使用该grep
命令来实现此目的,但不太成功。除了 之外还有什么命令可以使用吗grep
?
答案1
使用awk
:
awk -F'(^| )...|-' '$2>300 && $2<425 || $4>300 && $4<425' infile
在这里,我们将字段分隔符设置为:
- 行首后跟 3 个字符
^...
,或者 - 一个空格后跟 3 个字符
...
,或者 - 连字符
然后基于这些,第 2 列和第 4 列将是氨基酸的残基,因此我们检查它是否在给定范围内。
答案2
众所周知,主要处理正则表达式的工具不擅长处理数字。在这种情况下,我建议使用类似的东西awk
来代替grep
:
$ awk '{ r1 = substr($1,4,3); r2 = substr($2,4,3) } (r1 >= 300 && r1 <= 425) || (r2 >= 300 && r2 <= 425)' file
ARG262-Side ASP368-Side 140,83%
LEU354-Main LYS365-Main 93,6%
ARG346-Side GLU263-Side 93,57%
LEU301-Main ALA247-Main 93,43%
TYR424-Side ASN446-Main 93%
该awk
代码从每行的前两个空格分隔字段中提取从偏移量 4 开始的树字符,并调用它们r1
和r2
。我用来substr()
提取字段数据中固定位置的数字,但如果您确定唯一的数字是您感兴趣的数字,您也可以删除所有非数字。这样做
r1 = $1; gsub("[^[:digit:]]", "", r1)
类似地r2
使用$2
.
如果末尾的条件为真,则将打印当前行。
答案3
尝试这个:
grep -E '[^0-9](3[0-9][0-9]|4[01][0-9]|42[0-5])-' file`
-E
启用扩展正则表达式(不需要反斜杠括号和管道)[^0-9](
-- 非数字,后跟3[0-9][0-9]|
300 到 399 之间的数字,或者4[01][0-9]|
400 到 419 之间的数字,或者42[0-5]
420 到 425 之间的数字
)-
后跟一个连字符
提供非数字要求意味着您不匹配ABC1234-Something
答案4
grep -E "(^[[:upper:]]{3}(3[0-9]{2}|4([0-1][0-9]|2[0-5]))|\b[[:upper:]]{3}(3[0-9]{2}|4([0-1][0-9]|2[0-5])))" sample.txt
grep -E
具有扩展的正则表达式。
^[[:upper:]]{3}
:如果该行以三个大写字母字符开头
3[0-9]{2}
:匹配任何大于或等于300的数字序列
|
: 或者
4([0-1][0-9]|2[0-5])
:400 到 425 之间。
|
:或者(这里看第二栏)
\b
:世界是有边界的(有空间)
[[:upper:]]{3}(3[0-9]{2}|4([0-1][0-9]|2[0-5]))
: 与第一条路径相同。