如何拆分文本文件中给定列的字符串值

Mic*_*erk 2 sed awk text-processing bioinformatics

我在 Linux 机器上有一个包含两列的文本文件:

  • 第1列 = id_no(大部分为5位,有的为6位);
  • 第 2 列 = Genetic_markers(全部长度为 50674 位);
12345 0102010205
54322 2221110051
123456 1122011510
Run Code Online (Sandbox Code Playgroud)

我想将文件更改为如下所示:

 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0
Run Code Online (Sandbox Code Playgroud)
  1. 如何更改第一列,使其向右对齐(如数字所示)?

  2. 有人可以帮我用最可靠的方法来更改第二列数字之间的空格吗?请解释代码的元素及其作用。

谢谢

Sté*_*las 7

perl

$ perl -lane 'printf "%6s %s\n", $F[0], join " ", split "", $F[1]' <your-file
 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0
Run Code Online (Sandbox Code Playgroud)

使用-lane-n一次读取输入一条记录,并-e使用 中的记录运行表达式$_-a因为awk 将行拆分为@F字段,从记录中-l删除ine 分隔符),其行为类似于。lperlawk

在这里,我们使用printf空格将第一个字段左填充到 6 的长度,然后用空格将join第二个字段拆分为其字符组成部分。


ter*_*don 5

为了右对齐,您需要找到文件中最长数字的长度,或者只选择一个大数字并使用它。例如,您可以填充 10 个空格:

$ printf '%d\n' 123
123
$ printf '%10d\n' 123
       123
Run Code Online (Sandbox Code Playgroud)

如果这种方法足够好,您可以执行以下操作:

$ awk '{ gsub(/./," &",$2); printf "%10d%s\n",$1,$2}' file 
     12345 0 1 0 2 0 1 0 2 0 5
     54322 2 2 2 1 1 1 0 0 5 1
    123456 1 1 2 2 0 1 1 5 1 0
Run Code Online (Sandbox Code Playgroud)

这里只发生了两件事:

  • gsub(/./," &",$2);gsub( g lobal sub stitution) 函数将用您提供的任何替换项替换您给它的正则表达式的所有匹配项(这里,我们只给它一个.含义“任何字符”)。具有&特殊含义,表示“正则表达式匹配的任何内容”,因此 &作为替换给出的效果是在每个字符之前插入一个空格。最后一个参数是输入,这里我们给它第二个字段$2
  • printf "%10d %s\n",$1,$2:我们用来printf打印格式化字符串。%10d意思是“打印我给你的数字并用10个空格填充”,%s意思是“打印这个字符串”。因此,我们告诉它打印第一个字段填充了 10 个空格,然后打印已被 修改的第二个字段gsub

如果只需要填充最小值,则需要读取文件两次。首先获取最长的第一个字段的长度:

$ awk -v max=0 '{ if(length($1) > max){ max=length($1) }} END{print max}' file 
6
Run Code Online (Sandbox Code Playgroud)

有了这个,你就可以更具体:

$ awk '{ k=gsub(/./," &",$2); printf "%6d%s\n",$1,$2}' file 
 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0
Run Code Online (Sandbox Code Playgroud)