bash は行を列に変換します。

bash は行を列に変換します。

次の何千ものファイルがあります。

組織文書:

reference_group1 _CEFNB_
group1          ACBF_BG
group2          ACB_MBM
...

各ファイルに対して行を列に変換し、次のようにreference_groupのインデックスで構成される列(id_from_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の各グループの2番目の列の内容は、繰り返される文字で構成されています。そして、2番目の列の長さは常に同じです。

頑張った

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_group保存しますser。次に、ループ内の両方の変数を使用します。

これにより、次の行が機能します。

awk -f tst.awk file

出力形式を指定したら、column出力を次にパイプできます。column -t

awk -f tst.awk file | column -t

awkスクリプトの指示:

  • BEGIN最初の入力レコードの前に一度だけ実行されます。
  • $1 ~ /^reference_/$1正規表現と一致する場合^reference_
  • length($2)2番目のフィールドの長さ
  • substr(ser,i,1)ser位置と長さでi始まる部分文字列1

関連情報