我有一个文件 A.txt (sep = \t
,第一列为空):
Cycle A1 A2 B1
1 4 5 2
2 7 3 4
3 3 2 5
我想将此文件转换为新文件 B.txt (sep = \t
) :
Well Cycle Value
A1 1 4
A1 2 7
A1 3 3
A2 1 5
A2 2 3
A2 3 2
B1 1 2
B1 2 4
B1 3 5
我尝试了一些东西:awk '{for (i=1;i<=NF;i++) print $i}'
但我无法弄清楚。有人知道如何做到这一点吗?谢谢
答案1
不是awk
,但是使用磨坊主,给定
$ cat file
Cycle A1 A2 B1
1 4 5 2
2 7 3 4
3 3 2 5
然后
$ mlr --pprint --ifs tab reshape -i A1,A2,B1 -o Well,Value then sort -f Well then reorder -f Well file
Well Cycle Value
A1 1 4
A1 2 7
A1 3 3
A2 1 5
A2 2 3
A2 3 2
B1 1 2
B1 2 4
B1 3 5
sort
如果不需要,您可以省略该步骤。
Millerreshape
命令还可以接受用于字段选择的正则表达式。
reshape -r '[A-Z][1-9]' -o Well,Value
答案2
我们首先将文件加载到数组的数组中,AoA[colidx, rowidx]
然后在文件块的末尾,我们以我们想要的格式重组该数据。
笔记:
- 字段分隔符是
\t+
遍历连续的选项卡而不是传递空字段。 - 该
gsub()
部分是删除前 n 个尾随制表符。 - 此代码将处理与文件一样多的列和行。(内存允许)
awk -F '\t+' '
gsub(/^\t|\t$/, "") {$1=$1}
NR==1 {header = "Well" OFS $1 OFS "Value"}
{
for(i=1; i<=NF; i++) {
AoA[i, NR] = $(i)
}
}
END {
print header
for(col=2; col<=NF; col++) {
for(row=2; row<=NR; row++) {
well = AoA[col, 1]
cycle = AoA[1, row]
value = AoA[col, row]
print well, cycle, value
}
}
}
' OFS='\t' - | column -t
结果:
Well Cycle Value
A1 1 4
A1 2 7
A1 3 3
A2 1 5
A2 2 3
A2 3 2
B1 1 2
B1 2 4
B1 3 5
答案3
这是一种(相当粗糙)的方法,要求标头是静态的并且提前已知,并且不能很好地排序:
$ awk -F'\t' -v OFS="\t" 'BEGIN{print "Well","Cycle","Value"}
NR>1{
cycle[NR]=$2;
a1[NR]=$3;
a2[NR]=$4;
b1[NR]=$5;
}
END{
for(line in cycle){
print "A1",cycle[line],a1[line];
print "A2",cycle[line],a2[line];
print "B1",cycle[line],b1[line]
}
}' file
Well Cycle Value
A1 1 4
A2 1 5
B1 1 2
A1 2 7
A2 2 3
B1 2 4
A1 3 3
A2 3 2
B1 3 5
如果你需要很好地排序,你可以使用更粗略的:
$ awk -F'\t' -vOFS="\t" 'BEGIN{print "Well","Cycle","Value"}
NR>1{
cycle[NR]=$2;
a1[NR]=$3;
a2[NR]=$4;
b1[NR]=$5;
}
END{
for(line in cycle){
print "A1",cycle[line],a1[line];
}
for(line in cycle){
print "A2",cycle[line],a2[line];
}
for(line in cycle){
print "B1",cycle[line],b1[line]
}
}' file
Well Cycle Value
A1 1 4
A1 2 7
A1 3 3
A2 1 5
A2 2 3
A2 3 2
B1 1 2
B1 2 4
B1 3 5