次の何千ものファイルがあります。
組織文書:
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