すべての対応する値に対して行を繰り返したい。どんな助けでも
私の入力ファイルは次のとおりです
pos COL1 COL2 COL3
18691441 C A G
18691572 G C G
18691620 A T G
18691716 C G C
私はこの出力が欲しい
pos COL1
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C
行を繰り返そうとしていますが、繰り返されます。
while read line; do for i in {1..3}; do echo "$line"; done; done < real2.txt
出力を提供します。
pos COL1 COL2 COL3
18691441 C A G
18691441 C A G
18691441 C A G
18691572 G C G
18691572 G C G
18691572 G C G
18691620 A T G
18691620 A T G
18691620 A T G
18691716 C G C
18691716 C G C
18691716 C G C
次に、入力された1.txtファイルからposを抽出して1_pos.txtを作成し、次のように作成しました。
pos
18691441
18691572
18691620
18691716
for i in `cat 1_post.txt`;
do
x=$(grep -i "^$i" 1.txt | awk 'FNR == 1 {print $1"\t""COL1""\t"$2}' ) ;
y=$(grep -i "^$i" 1.txt | awk 'FNR == 1 {print $1"\t""COL2""\t"$3}' ) ;
z=$(grep -i "^$i" 1.txt | awk 'FNR == 1 {print $1"\t""COL3""\t"$4}' ) ;
echo -e "$x""\n""$y""\n""$z";
done
これにより、列情報を含む出力が得られますが、3つではなく405列がある場合は、各列に対して行を405回繰り返したくないため、ループに入れようとしましたが機能しません。
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C
答え1
どうですか?
while read line col1 col2 col3;
do
if [[ "$line" = "pos" ]]; then
echo "pos COL"
continue
fi
echo "$line COL1 $col1"
echo "$line COL2 $col2"
echo "$line COL3 $col3"
done < real2.txt
出力:
pos COL
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C
答え2
アッ方法:
awk 'BEGIN{OFS="\t";print "pos" OFS "COL1"}{if(NR==1){for(f=2;f<=NF;f++) c[f]=$f;}
else{for(i=2;i<=NF;i++) print $1,c[i],$i}}' real2.txt
出力:
pos COL1
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C
OFS="\t"
- 出力フィールド区切り記号
print "pos" OFS "COL1"
- 印刷ヘッダーワイヤー
if(NR==1){for(f=2;f<=NF;f++) c[f]=$f;
- 最初の行/ヘッダー行から列名を収集する
for(i=2;i<=NF;i++) print $1, c[i], $i
COL...
pos
- 対応する列の値とその列名に基づいて、各列()の値を「行単位」で印刷します。
答え3
テキストを処理するためにシェルループを使用しないでください。
これはawk
仕事に適したツールです。しかし、一度だけ呼び出すだけです。
awk -v OFS='\t' '
NR == 1 {print $1, "name", "value"; split($0, header); next}
{for (i = 2; i < NF; i++) print $1, header[i], $i}' < your-file
(変形ローマ人の答え)
答え4
while IFS= read -r l; do
read -r -a A <<<"$l"
case $l in
'pos'[\ \ ]* )
echo "${A[@]:0:2}"
C=("${A[@]:1}")
;;
* )
p=0 x=${A[0]}
for e in "${A[@]:1}"; do
echo "$x ${C[$p]} $e"
((p++))
done
;;
esac
done < yourfile
sed -E '
/\n/bloop
y/\t/ /;s/ +/ /g;s/^ +//;s/ +$//
1{
h
s/ /\n/2
x
s/ /\n/;s/.*\n//
x
s/\n.*//
b
}
G;s/\n/ &/
:loop
# 1 2 3 4 5
s/^(\S+ )(\S+) (.*)(\n)(\S+) ?/\1\5 \2\4\1\3\4/
/\n$/{
/\n.*\n/!d
}
P
/\n.*\n/D
tloop
' yourfile
結果
pos COL1
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C
説明する
- まず、残りのすべてのタブをスペースに変換してから複数のスペースを圧縮し、最後にすべての前後のスペースを切り取ります。
- 最初の行に対して特別な処理を実行します。
- a) ラインをコピーします。
- b) 後で使用できるように、2 番目の列の終わりを表示します。
- c)このマークされた行を予約済みスペースに保存されているコピーに置き換えます。
- d)最初の列を削除し、cols1,2の&マークを復元します。
- 他のすべての行(2〜eof)の場合は、列名を行に追加します。
do-while
次に、繰り返すたびに表示された方法でフィールドを並べ替えて、列名とその値が印刷されるようにループを設定します。行の終わりが見え、その行に残っている唯一の文字が表示されたら停止します\n
。\n
それ以外の場合は、前の部分を切り取り、ループの先頭に再分岐します。