使用 unix(awk、sed、bash?)通过第 4 个下划线截断列中的项目?
Using unix (awk, sed, bash?) to truncate items in a column by the 4th underscore?
我有一系列看起来像这样的文件,第二列和第三列是重复的,但有数千行。
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2_i1.p1 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1_i2.p1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1_i1.p1 6.26e-66
我想截取第 3 列,以便删除字符串中包括 _i 之后的所有内容,如下所示:
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
每个字母组合(DN、c、g、i、p)后面的数字可以是任何东西,也可以是任何长度,所以我不能只截断到一定长度。
我试过了sed -i 's/_i.*//' file.txt
但是这删除了每一行之后的所有内容,而不仅仅是感兴趣的列。
非常感谢!
使用sed
$ sed -i.bak 's/\(g[0-9]*\)_[^ ]*//2' input_file
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
您可以在第二次匹配时进行替换
这将使用 GNU sed 来完成:
sed 's/\(.*_i.*\)_i.*\(\s.*\)//' your_file > output_file
\(
和\)
是捕获组,记住里面匹配的东西
\(.*_i.*\)_i.*
记住直到(但不包括)第二个 _i
的所有内容
\(\s.*\)
记住从第二个 _i
之后的 space 到行尾 的所有内容
//
用第一个和第二个捕获组替换该行(即删除从第二个 _i
到第一个 space 的所有内容。
产出
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
awk '{sub(/_[^_]+$/,"",)}1' file
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
在第 3 个字段中删除最后一个下划线(包括)之后的所有内容。
您可以使用 awk 从第一次出现的 _i
中删除,然后是第三个字段中的其余行:
awk 'sub(/_i.*/, "", )1' file
输出
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
一个 perl 单行代码:
perl -lane '$F[2] = join "_", (split /_/, $F[2])[0..3]; print "@F"' file
用下划线拆分第 3 个字段,获取前 4 个组件并用下划线连接它们。
我有一系列看起来像这样的文件,第二列和第三列是重复的,但有数千行。
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2_i1.p1 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1_i2.p1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1_i1.p1 6.26e-66
我想截取第 3 列,以便删除字符串中包括 _i 之后的所有内容,如下所示:
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
每个字母组合(DN、c、g、i、p)后面的数字可以是任何东西,也可以是任何长度,所以我不能只截断到一定长度。
我试过了sed -i 's/_i.*//' file.txt
但是这删除了每一行之后的所有内容,而不仅仅是感兴趣的列。
非常感谢!
使用sed
$ sed -i.bak 's/\(g[0-9]*\)_[^ ]*//2' input_file
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
您可以在第二次匹配时进行替换
这将使用 GNU sed 来完成:
sed 's/\(.*_i.*\)_i.*\(\s.*\)//' your_file > output_file
\(
和\)
是捕获组,记住里面匹配的东西\(.*_i.*\)_i.*
记住直到(但不包括)第二个_i
的所有内容
\(\s.*\)
记住从第二个_i
之后的 space 到行尾 的所有内容
//
用第一个和第二个捕获组替换该行(即删除从第二个_i
到第一个 space 的所有内容。
产出
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
awk '{sub(/_[^_]+$/,"",)}1' file
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
在第 3 个字段中删除最后一个下划线(包括)之后的所有内容。
您可以使用 awk 从第一次出现的 _i
中删除,然后是第三个字段中的其余行:
awk 'sub(/_i.*/, "", )1' file
输出
AT1G15820.1 TRINITY_DN96909_c1_g2_i1.p1 TRINITY_DN96909_c1_g2 1.36e-115
AT1G15820.1 TRINITY_DN96909_c1_g1_i2.p1 TRINITY_DN96909_c1_g1 9.97e-113
AT1G15820.1 TRINITY_DN96909_c1_g1_i1.p1 TRINITY_DN96909_c1_g1 6.26e-66
一个 perl 单行代码:
perl -lane '$F[2] = join "_", (split /_/, $F[2])[0..3]; print "@F"' file
用下划线拆分第 3 个字段,获取前 4 个组件并用下划线连接它们。