Bash 如何从特定列中的模式中删除文本

Bash 如何从特定列中的模式中删除文本,bash,tabular,Bash,Tabular,我有一个表文件,例如: qseqid sseqid pident length mismatch gapopen qstart qend sstart send evalue bitscore strand scaffold EOG091B09QV:/path/path/Z xx a 1:8830-20153 74.3 144 0 1 scaffold EOG091B09QV:/path/path/A x

我有一个表文件,例如:

qseqid  sseqid  pident  length  mismatch    gapopen qstart  qend    sstart  send    evalue  bitscore    strand

scaffold    EOG091B09QV:/path/path/Z    xx  a   1:8830-20153    74.3    144 0   1
scaffold    EOG091B09QV:/path/path/A    x   a   1:8830-20153    100.0   93  0   0
scaffold    EOG091B09QV:/path/path/Q    x   a   1:8830-20153    41.3    189 49  3
scaffold    EOG091B09QV:/path/path/U    x   a   1:8830-20153    87.5    48  6   0
scaffold    EOG091B09QV:/path/path/K    x   a   1:8830-20153    100.0   60  0   0
我们的想法是简单地删除sseqid列中
并获得:

qseqid  sseqid  pident  length  mismatch    gapopen qstart  qend    sstart  send    evalue  bitscore    strand

scaffold    EOG091B09QV xx  a   1:8830-20153    74.3    144 0   1
scaffold    EOG091B09QV x   a   1:8830-20153    100.0   93  0   0
scaffold    EOG091B09QV x   a   1:8830-20153    41.3    189 49  3
scaffold    EOG091B09QV x   a   1:8830-20153    87.5    48  6   0
scaffold    EOG091B09QV x   a   1:8830-20153    100.0   60  0   0

我知道
cut-f 1-d:“
匹配
\u species\u strand\u H.m8
可以工作,但不能在特定列中工作。

我更喜欢Perl来处理这些事情:

cat inputfile | perl -ne '@in=split(/\s/);$in[1]=~s/:(.*)$//;print(join(" ",@in));print "\n"'

perl-ne在每个输入行上循环,将行拆分为一个数组,替换第二个元素中的内容并将数组连接在一起

对于这样的事情,我更喜欢Perl:

cat inputfile | perl -ne '@in=split(/\s/);$in[1]=~s/:(.*)$//;print(join(" ",@in));print "\n"'

perl-ne在每个输入行上循环,将行拆分为一个数组,替换第二个元素中的内容并将数组连接在一起

您可以使用
sed
非常轻松地执行此操作:

sed -r 's/^(\S+\s+[^:[:space:]]+):\S+/\1/g' filename

括号内的部分与第一列、第一列和第二列之间的空格以及第二列的部分匹配,直到(但不包括)字符
:\S+
与第二列的其余部分匹配。然后,将该行的整个匹配部分替换为括号内的部分,该部分由
\1

表示。使用
sed
可以非常轻松地执行此操作:

sed -r 's/^(\S+\s+[^:[:space:]]+):\S+/\1/g' filename

括号内的部分与第一列、第一列和第二列之间的空格以及第二列的部分匹配,直到(但不包括)字符
:\S+
与第二列的其余部分匹配。然后将行的整个匹配部分替换为括号内的部分,该部分由
\1

表示。awk是处理基于列的文本的最佳选择:

awk 'sub(/:.*/,"",$2)+7' file

将执行以下操作:“从第二列中删除
:.*

awk是处理基于列的文本的一个好选择:

awk 'sub(/:.*/,"",$2)+7' file

将完成任务:“从第二列中删除
:.*

我更喜欢这个解决方案。它更短更清晰。但是,它用一个空格字符替换列之间的所有空格(但仅在它修改的行上)。这可能是OP的问题,也可能不是。如果输入文件中的多个空格是出于格式化目的故意存在的,那可能是个问题。@MikeHolt如果格式有问题,可以尝试使用管道连接到
| column-t
我更喜欢这个解决方案。它更短更清晰。但是,它用一个空格字符替换列之间的所有空格(但仅在它修改的行上)。这可能是OP的问题,也可能不是。如果输入文件中的多个空格是出于格式化目的故意存在的,那可能是个问题。@MikeHolt如果格式有问题,可以尝试使用管道连接到
|column-t