![如何为其对应列的每个值重复一行](https://linux22.com/image/111206/%E5%A6%82%E4%BD%95%E4%B8%BA%E5%85%B6%E5%AF%B9%E5%BA%94%E5%88%97%E7%9A%84%E6%AF%8F%E4%B8%AA%E5%80%BC%E9%87%8D%E5%A4%8D%E4%B8%80%E8%A1%8C.png)
我想为其所有相应的值重复一行任何帮助
我的输入文件是这样的
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
这给了我带有列信息的输出,但是如果我有 405 列而不是 3 列,我不想为每列重复行 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方法:
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) 标记第二列的末尾以供稍后使用。
- c) 将此标记行与存储在保留空间中的副本互换。
- d) 剥离第一列,然后恢复显示 cols1,2 中的 &。
- 对于所有其他行(2 到 eof),我们将列名称附加到该行。
- 然后设置一个
do-while
循环,在每次迭代中我们以所示的方式重新排列字段,以便打印出列名称及其值。当我们看到一行的末尾并且它是该行中剩余的\n
唯一字符时,我们停止。\n
否则,我们只需砍掉前导部分并分支回到循环开头。