删除列中的扩展名

删除列中的扩展名

我有一个这样的文件

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/\..*//'

相关内容