我有想要格式化的字符串。我想删除第二个;
和倒数第二个之间的所有内容;
。
输入
cellular organisms;Eukaryota;Opisthokonta;Metazoa;Eumetazoa;Bilateria;Protostomia;Ecdysozoa;Panarthropoda;Arthropoda;Mandibulata;Pancrustacea;Hexapoda;Insecta;Dicondylia;Pterygota;Neoptera;Endopterygota;Coleoptera;Polyphaga;Cucujiformia;Tenebrionoidea;Tenebrionidae;Tenebrionidae incertae sedis;Tribolium;Tribolium castaneum;
输出
cellular organisms;Eukaryota;Tribolium castaneum;
我尝试过使用sed
sed 's/;[^;]*//' <<<"cellular organisms;Eukaryota;Opisthokonta;Metazoa;Eumetazoa;Bilateria;Protostomia;Ecdysozoa;Panarthropoda;Arthropoda;Mandibulata;Pancrustacea;Hexapoda;Insecta;Dicondylia;Pterygota;Neoptera;Endopterygota;Coleoptera;Polyphaga;Cucujiformia;Tenebrionoidea;Tenebrionidae;Tenebrionidae incertae sedis;Tribolium;Tribolium castaneum;"
产生
cellular organisms;Opisthokonta;Metazoa;Eumetazoa;Bilateria;Protostomia;Ecdysozoa;Panarthropoda;Arthropoda;Mandibulata;Pancrustacea;Hexapoda;Insecta;Dicondylia;Pterygota;Neoptera;Endopterygota;Coleoptera;Polyphaga;Cucujiformia;Tenebrionoidea;Tenebrionidae;Tenebrionidae incertae sedis;Tribolium;Tribolium castaneum;
答案1
您可以使用以下方法轻松完成此操作awk
:
awk -F\; '{print $1 ";" $2 ";" $(NF-1) ";" $NF}'
;
这使用( )分割输入-F\;
,并打印第一个 ( $1
)、第二个 ( $2
)、倒数第二个和最后一个字段($(NF-1)
并且$NF
;NF
包含字段数)。
以下变体在输出中重新使用指定的字段分隔符:
awk -F\; '{print $1 FS $2 FS $(NF-1) FS $NF}'
贾尼斯也建议使用改进版本OFS
:
awk 'BEGIN{FS=OFS=";"} {print $1,$2,$(NF-1),$NF}'
或者,如果您想将分隔符保留为另一个参数:
awk -F\; 'BEGIN{OFS=FS} {print $1,$2,$(NF-1),$NF}'
答案2
一些 Perl 方法。在所有情况下,我都运行此命令来填充$string
:
string="cellular organisms;Eukaryota;Opisthokonta;Metazoa;Eumetazoa;Bilateria;Protostomia;Ecdysozoa;Panarthropoda;Arthropoda;Mandibulata;Pancrustacea;Hexapoda;Insecta;Dicondylia;Pterygota;Neoptera;Endopterygota;Coleoptera;Polyphaga;Cucujiformia;Tenebrionoidea;Tenebrionidae;Tenebrionidae incertae sedis;Tribolium;Tribolium castaneum;"
$ perl -F';' -lane '$"=";"; print "@F[0,1,$#F-1];"' file
cellular organisms;Eukaryota;Tribolium castaneum;
或者
$ perl -F';' -lane 'print "$F[0];$F[1];$F[$#F];"' <<<"$string"
cellular organisms;Eukaryota;Tribolium castaneum;
或者
$ perl -F';' -lane 'print join(";", @F[0,1,$#F-1]) . ";"' <<<"$string"
cellular organisms;Eukaryota;Tribolium castaneum;
答案3
另一种sed
方法:
sed 's/\(^[^;]*\;[^;]*\).*\(\;[^;]*\;$\)/\1\2/'
输出: cellular organisms;Eukaryota;Tribolium castaneum;
答案4
sed -n 's/\(;[^;]*;\).*\(;.*;\)/\1\2/p' <infile
...上面只会p
打印匹配至少 4 个;
字符的输入行的任何内容,并且对于这些输入行,只会打印之前和之后的内容,并分别包括第二个和倒数第二个出现的;
字符。
不过,如果您首先验证您至少有四个,则可以更轻松地执行以下操作:
sed -n '/\(;.*\)\{4\}/s/[^;]*//3p' <infile
首先确保该行至少匹配 4 ;
,然后删除第三个出现的零个或多个非分号字符序列。该测试是必要的,因为s///
替换可以应用于任何匹配至少 2 个分号的行 - 因此测试可以确保是;
在尝试剥离之前添加倒数第二个分号。
上述两个建议的解决方案仅打印替换成功的那些行。您可以通过删除-n
和p
命令来打印所有行 - 仍然会尝试替换,并且只打印它们匹配的行的结果,但无论如何都会打印其他所有行。
当然,如果您确定自己的输入,您所需要的只是:
sed 's/[^;]*//3' <infile