将列合并为一列(堆栈)

将列合并为一列(堆栈)

我有多列数据,我希望重新格式化,使每一列在一个列中彼此“重叠”。

输入示例:

1  2  3  4
1  2  3  4

期望的输出:(修复了缺少“1”和“3”的旧拼写错误

1
1
2
2
3
3
4
4

(有时我也想在列之间添加空格)

编辑: 关于“之间的空格”的评论不清楚。有时我想要在堆叠的列之间有一个空行。改编下面埃德·莫顿接受的答案,这可以通过以下方式实现

awk '
{for (i=1; i<=NF; i++) a[i]=a[i] $i ORS}
END {for (i=1; i<=NF; i++) printf "%s", a[i](i==NF?"":"\n")}
' file

答案1

用于datamash转置数据,然后tr将空格转换为换行符(同时-s将多个空格压缩为一个)。

datamash -t' ' transpose <infile | tr -s ' ' '\n'

答案2

这可能就是您想要的,在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ awk '
    { for (i=1; i<=NF; i++) a[i] = a[i] $i ORS }
    END { for (i=1; i<=NF; i++) printf "%s", a[i] }
' file
1
1
2
2
3
3
4
4

答案3

GNU grep 怎么样:

grep -o '\S*' infile

或者,扩展(相当于)\S

grep -o '[^ \t\r\n\v\f]*' infile

如果需要保留列的顺序,请尝试(使用GNU排序)

$ awk '{for (i=1;i<=NF;i++){ print i,$i }}' infile | 
      sort -snbk 1,1 | 
      awk '{$1=""}1'

1
1
2
2
3
3
4
4

或者,仅使用awk, 以及类似于转置列的过程:

awk '{ for(i=1;i<=NF;i++) { f[i]=(f[i]==""?"":f[i] ORS) $i; if(NF>n) n=NF}}
       END { for(i=1; i<=n; i++) { print f[i] }  }
    '  infile

答案4

这个答案依赖于切换打印列和行的顺序,实际上生成原始数据的转置。

OP 的问题中更新了相同的输出,正如预期的那样,它最初是不正确的。

for i in `seq 4`; do 
    awk -v field=$i '{ print $field }' infile; 
done

1
1
2
2
3
3
4
4

相关内容