我有一个这样的文件
ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402.5
ILMN_1343295 CTTCAACAGCGACACCCACTCCTCCACCTTTGACGCTGGGGCTGGCATTG NM_002046.3
ILMN_1651209 TCACGGCGTACGCCCTCATGGGGAAAATCTCCCCGGTGACTTTCAGGTCC NM_182838.1
我想删除第三列末尾的数字扩展名,以便我的输出文件如下所示
ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402
ILMN_1343295 CTTCAACAGCGACACCCACTCCTCCACCTTTGACGCTGGGGCTGGCATTG NM_002046
ILMN_1651209 TCACGGCGTACGCCCTCATGGGGAAAATCTCCCCGGTGACTTTCAGGTCC NM_182838
我怎样才能最好使用命令行来完成它awk
?我可以做到这一点,perl
但我很确定有一个命令行可以做到这一点。
答案1
使用 awk:
awk -F'.' '{print $1}' file
-F
选项将默认字段分隔符(空格)更改为点(.)。
$1
是字段位置的索引(带有 . 字段分隔符)。
{ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402}.{5}
^^ field index is $1 ^^$2
使用 rev 和 awk:
rev file | awk -F'.' '{print $2}'|rev # reverse characters of each lines,\
print field number 2 with (.) separator \
and reverse the result again
该rev
实用程序将指定的文件复制到标准输出,反转每行中的字符顺序。如果未指定文件,则读取标准输入。
使用 sed:
sed 's/.[0-9]*$//' file
sed 's/.[^.]*$//' file
$
指向行尾。在第一个 sed 命令中搜索 char(.),后跟零个或多个出现的数字,并将它们替换为空格。
在第二个 sed 命令中,删除 (.) 后面的所有内容,并删除点 (.) 本身。
使用 rev 和 sed:
rev file| sed 's/.*[.]//' |rev
删除点(.)之前的所有内容,同时包含和删除 .本身。
使用 grep:
grep -oP '.*(?=\.[0-9])' file
-o, --仅匹配 仅打印匹配行的匹配(非空)部分, 每个这样的部分都在单独的输出线上。 -P, --perl-正则表达式 将 PATTERN 解释为 Perl 兼容的正则表达式 (PCRE)
(?=pattern)
:正向先行:正向先行构造是一对括号,左括号后跟一个问号和一个等号。
.*(?=\.[0-9])
:(正向先行)匹配所有内容 ( .*
) 后跟一个点 (.) 和任何出现的数字,而不使模式 ( \.[0-9]
) 成为匹配的一部分。
使用 rev 和 grep:
rev file |grep -oP '(?<=[0-9]\.).*' |rev
rev file |grep -oP '[0-9]\.\K.*' |rev
(?<=pattern)
:积极的后视。一对括号,左括号后跟一个问号、“小于”符号和一个等号。
(?<=[0-9]\.).*
(正向后查找)匹配后面出现的任何数字并以点 (.) 结尾的所有内容。
在第二个 grep 命令中,您可以使用 nifty\K
代替lookbehind 断言。
带切割:
cut -f1 -d. file
cut -c 1-77 file # Print first 77 characters of each line.
cut - 从文件的每一行中删除部分 -d, --delimiter=DELIM 使用 DELIM 而不是 TAB 作为字段分隔符 -f, --fields=列表 仅选择这些字段; -c, --字符=列表 仅选择这些字符
使用 while 循环:
while read line; do echo "${line::-2}";done <file
如果每行末尾只有长度为 1 的数字并且它们是固定长度,则这将起作用。上面的命令删除输入文件中每行末尾的最后两个字符。替代命令是${line%??}
.
答案2
假设扩展名是全数字:
perl -pi -e 's/\.\d+$//' /path/to/file
-i
进行就地编辑(如sed
)。\d
表示数字,$
表示行尾。
和awk
:
awk 'gsub(/\.[0-9]+$/,"")' /path/to/file
gawk
在较新的版本中有一个就地编辑选项,但我不确定它的便携性如何。gsub
支持可选参数,指定目标列:
awk 'gsub(/\.[0-9]+$/,"",$3)' /path/to/file
最后一种形式具有不良的副作用,即在其输出中用单个空格分隔每列,就像您所做的那样print $1,..,$NF
。我不知道为什么。
答案3
使用awk
它很简单,只需将字段分隔符设置为.
:
awk -F. '{print $1}' file
另一种方法是使用 shell(在本例中为 bash):
while IFS=.; read -r lines _; do line+=("$lines"); done <file
printf "%s\n" "${line[@]}"
ILMN_1343291 TGTGTTGAGAGCTTCTCAGACTATCCACCTTTGGGTCGCTTTGCTGTTCG NM_001402
ILMN_1343295 CTTCAACAGCGACACCCACTCCTCCACCTTTGACGCTGGGGCTGGCATTG NM_002046
ILMN_1651209 TCACGGCGTACGCCCTCATGGGGAAAATCTCCCCGGTGACTTTCAGGTCC NM_182838
答案4
这会删除以点开头的所有内容:
sed 's/\..*//'