![从每一行中提取特定字符](https://linux22.com/image/160205/%E4%BB%8E%E6%AF%8F%E4%B8%80%E8%A1%8C%E4%B8%AD%E6%8F%90%E5%8F%96%E7%89%B9%E5%AE%9A%E5%AD%97%E7%AC%A6.png)
我有一个文本文件,我想从后面的每一行中提取字符串"OS="
input file line
A0A0A9PBI3_ARUDO Uncharacterized protein OS=Arundo donax OX=35708 PE=4 SV=1
K3Y356_SETIT ATP-dependent DNA helicase OS=Setaria italica OX=4555 PE=3 SV=1
所需输出
OS=Arundo donax
OS=Setaria italica
或者
Arundo donax
Setaria italica
答案1
使用带有扩展正则表达式的 GNU grep
(或兼容版本):
grep -Eo "OS=\w+ \w+" file
或基本正则表达式(你需要转义+
grep -o "OS=\w\+ \w\+" file
# or
grep -o "OS=\w* \w*" file
要获得从OS=
到 的所有内容,OX=
您可以使用grep
与 perl 兼容的正则表达式(PCRE)(-P
选项)(如果可用)并进行前瞻:
grep -Po "OS=.*(?=OX=)" file
#to also leave out "OS="
#use lookbehind
grep -Po "(?<=OS=).*(?=OX=)" file
#or Keep-out \K
grep -Po "OS=\K.*(?=OX=)" file
或者使用grep
包含OX=
并随后删除它sed
:
grep -o "OS=.*\( OX=\)" file | sed 's/ OX=$//'
输出:
OS=Arundo donax
OS=Setaria italica
答案2
在 Perl 中,两个非空白“单词”:
$ perl -lne 'print $1 if /OS=(\S+ \S+)/' input
或以下所有内容OX=
:
$ perl -lne 'print $1 if /OS=(.*?) OX=/' input
或接下来的一切something=
:
$ perl -lne 'print $1 if /OS=(.*?) (\w+)=/' input
对于您的示例输入,它们都给出相同的输出,但输出会有所不同,例如这样的输入:
ABC=something here OS=foo bar doo PE=3 OX=1234
答案3
更可靠的方法是使用 sed 解析完整值,直到找到包含下一个 = 的单词。这样,它将适用于任何大小的值(例如,如果您的字体包含一个单词或三个单词)。
sed 's/.*OS=\([^=]*\).*/\1/;s/ [^ ]*$//'
第一个块捕获 之前的所有内容OS=
,捕获组中的第二个块(用\(\)
's 表示)与下一个块匹配=
,并且可以在替换中将其称为\1
。下一次替换将删除最后一个单词,该单词是下一次分配的片段。
注意:^
in[]
是排除匹配字符,在这种情况下是所有内容不是一个=
标志。
答案4
awk '{print $(NF-4), $(NF-3)}' file
OS=Arundo donax
OS=Setaria italica
或者
awk -F= '{sub(/OX/,""); print $(NF-3)}' file
Arundo donax
Setaria italica