bash 将行转换为列

bash 将行转换为列

我有数千个如下所示的文件:

组织文件:

reference_group1 _CEFNB_
group1          ACBF_BG
group2          ACB_MBM
...

对于每个文件,我需要将行转换为列,然后添加一列(称为 id_from_reference_group),该列由 reference_group 的索引组成,如下所示:

转换后的文件


# explanation of each column
# reference_group_id    serials_from_ref_group  group_id    serials_from_group
reference_group1            _                group1            A
reference_group1                             group1            C
reference_group1            E                group1            B
reference_group1            F                group1            F
reference_group1            N                group1            _
reference_group1            B                group1            B
reference_group1            _                group1            G
reference_group1            _                group2            A
reference_group1            C                group2            C
reference_group1            E                group2            B
reference_group1            F                group2            _
reference_group1            N                group2            M
reference_group1            B                group2            B
reference_group1            _                group2            M

每组org_files中第二列的内容由重复的字母组成。并且第二列始终具有相同的长度。

我试过

input="reference_group1 _CEFNB_
group1          ACBF_BG
group2          ACB_MBM"

while IFS=" " read -ra line; do # read input line by line
# loop over fields
  for (( i = 0 ; i < ${#line[@]}; i++ )); do
    # only split 2nd field
    if [[ $i == 1 ]]
    then
      for j in ${line[$i]}
      do
        # loopover each letter of 2nd field
        for (( j=0; j<${#line[$i]}; j++ ))
        do
          echo "${line[$i-1]}  ${line[$i]:$j:1}"
        done
      done
    fi

  done
done <<< "$input"

但我只得到这样的结果

reference_group1  _
...
group1  A
...
group2  M

而且代码有点乱。如果有简单的命令就更好了。谢谢!

答案1

您可以使用 awk 使用类似 ( ) 的脚本tst.awk

BEGIN{print "#reference_group_id serials_from_ref_group group_id serials_from_group"}
$1 ~ /^reference_/ {ref=$1;ser=$2;next}
{
        for(i=1;i<=length($2);i++){
                print ref, substr(ser,i,1), $1, substr($2,i,1)
        }
}

我认为您reference_group_id总是首先reference_将其存储到名为 的 var 中ref,然后将其存储serials_from_ref_groupser.然后我们在循环中使用这两个变量。

那么这样的一行应该可以工作:

awk -f tst.awk file

当您的输出被格式化时,column您可以将输出通过管道传输到column -t

awk -f tst.awk file | column -t

awk 脚本的说明:

  • BEGIN仅在第一个输入记录之前执行一次
  • $1 ~ /^reference_/if$1匹配正则表达式^reference_
  • length($2)第二个字段的长度
  • substr(ser,i,1)seri位置和长度开始的子串1

相关内容