You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用awk按特定条件实现文本行列转置?

行列转置需求的纯Awk实现方案

输入文件内容

cat f
"0/35","0eij8401c
"0/35","59ij41015
"0/35","21ij3e01c
"0/35","dbije401b
"1/35","dbij8a015
"1/35","67ijb9011
"1/35","b5ije001b
"1/35","bdij3701d
"2/35","abij3b011
"2/35","7fij70018
"2/35","77ijf9010
"2/35","e5ij64015
"3/35","59ij41015
"3/35","f6ijae01e
"3/35","c4ij5801c
"3/35","dbij98012
"4/35","edij6801e
"4/35","pdij6801e
"4/35","kdij6801e
"4/35","8cij57018

转置规则

  • 取第1、5、9、13、17行的第二列作为输出第一列
  • 取第2、6、10、14、18行的第二列作为输出第二列
  • 以此类推,最终生成4行5列的转置结果

期望输出

输出1(报表格式)

"0eij8401c  "dbij8a015  "abij3b011  "59ij41015  "edij6801e
"59ij41015  "67ijb9011  "7fij70018  "f6ijae01e  "pdij6801e
"21ij3e01c  "b5ije001b  "77ijf9010  "c4ij5801c  "kdij6801e
"dbije401b  "bdij3701d  "e5ij64015  "dbij98012  "8cij57018

输出2(单列格式)

0eij8401c
dbij8a015
abij3b011
59ij41015
edij6801e
59ij41015
67ijb9011
7fij70018
f6ijae01e
pdij6801e
21ij3e01c
b5ije001b
77ijf9010
c4ij5801c
kdij6801e
dbije401b
bdij3701d
e5ij64015
dbij98012
8cij57018

当前尝试的方法

方法1:Awk拆分+Paste合并

通过Awk将每行第二列按每4行拆分到不同文件:

cat f | awk -v batchNo=1 -v Num=4 '{print $1 > "batch_" batchNo ".txt";if(NR%Num==0) {batchNo++}}'

生成5个中间文件:

ls batch_*
batch_1.txt  batch_2.txt  batch_3.txt  batch_4.txt  batch_5.txt

再用Paste合并得到报表格式输出:

paste batch_1.txt batch_2.txt batch_3.txt batch_4.txt batch_5.txt

该方法能得到期望输出1,但依赖中间文件,需要纯Awk实现方案。

方法2:尝试的纯Awk命令(未成功)

awk '{a[$1]++; b[$2]++;c[$3]++;d[$4]++;e[$5]++} END {for (k in a) print k > "out.txt"; for (j in b) print j > "out.txt";for (k in c) print j > "out.txt";for(l in d) print l> "out.txt"; for (m in e) print m> "out.txt";}' batch_*

未得到理想结果。

纯Awk解决方案

实现期望输出1(报表格式)

核心思路:用二维数组存储每行第二列,行索引为(NR-1)%4,列索引为int((NR-1)/4),最后按行输出数组内容:

awk -F, '{arr[(NR-1)%4][int((NR-1)/4)] = $2} END {for(i=0;i<4;i++){for(j=0;j<5;j++){printf "%s  ", arr[i][j]} print ""}}' f
  • -F,:指定逗号为分隔符,提取第二列$2
  • (NR-1)%4:计算当前行对应的输出行号(0-3)
  • int((NR-1)/4):计算当前行对应的输出列号(0-4)
  • 遍历数组按行输出,每列用两个空格分隔

实现期望输出2(单列格式)

核心思路:按列遍历二维数组,依次输出元素,同时可选择去掉引号:

awk -F, '{arr[(NR-1)%4][int((NR-1)/4)] = $2} END {for(j=0;j<5;j++){for(i=0;i<4;i++){sub(/"/,"",arr[i][j]); print arr[i][j]}}}' f
  • sub(/"/,"",arr[i][j]):去掉字符串两端的引号(不需要可省略)
  • 先按列索引遍历,再按行索引遍历,实现目标单列顺序

内容的提问来源于stack exchange,提问作者VIPIN KUMAR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 06:24:25