awk - 内存高效转置 - Awk

标签 awk transpose

我正在尝试使用以下脚本转置表格(10k 行 X 10K 列)。

一个简单的数据示例

$ 猫 rm1

        t1      t2      t3
n1      1       2       3
n2      2       3       44
n3      1       1       1

$ sh 转置.sh rm1

        n1      n2      n3
t1      1       2       1
t2      2       3       1
t3      3       44      1

但是,我遇到了内存错误。任何帮助,将不胜感激。

awk -F "\t" '{
for (f = 1; f <= NF; f++)
a[NR, f] = $f
}
NF > nf { nf = NF }
END {
for (f = 1; f <= nf; f++)
for (r = 1; r <= NR; r++)
printf a[r, f] (r==NR ? RS : FS)
}'

错误

awk: cmd. line:2: (FILENAME=input FNR=12658) fatal: dupnode: r->stptr: can't allocate 10 bytes of memory (Cannot allocate memory)

最佳答案

正如我在评论中提到的那样,这是一种分 block 进行的方法。在这里,我展示了一个微型 12r x 10c 文件的机制,但我也在不到一分钟的时间内在 10K x 10K 文件上运行了 1000 行的 block ( Mac Powerbook).6

编辑 更新了以下内容以考虑行数和列数不相等的 M x N 矩阵。以前的版本仅适用于“N x N”矩阵。

$ cat et.awk
BEGIN {
    start = chunk_start
    limit = chunk_start + chunk_size - 1
}

{
    n = (limit > NF) ? NF : limit
    for (f = start; f <= n; f++) {
        a[NR, f] = $f
    }
}

END {
    n = (limit > NF) ? NF : limit

    for (f = start; f <= n; f++)
      for (r = 1; r <= NR; r++)
        printf a[r, f] (r==NR ? RS : FS)
}


$ cat t.txt
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29 
30 31 32 33 34 35 36 37 38 39 
40 41 42 43 44 45 46 47 48 49 
50 51 52 53 54 55 56 57 58 59 
60 61 62 63 64 65 66 67 68 69 
70 71 72 73 74 75 76 77 78 79 
80 81 82 83 84 85 86 87 88 89 
90 91 92 93 94 95 96 97 98 99 
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 


$ cat et.sh
inf=$1
outf=$2

rm -f $outf
for i in $(seq 1 2 12); do
    echo chunk for rows $i $(expr $i + 1)
    awk -v chunk_start=$i -v chunk_size=2 -f et.awk $inf >> $outf
done



$ sh et.sh t.txt t-transpose.txt
chunk for rows 1 2
chunk for rows 3 4
chunk for rows 5 6
chunk for rows 7 8
chunk for rows 9 10
chunk for rows 11 12


$ cat t-transpose.txt 
10 20 30 40 50 60 70 80 90 A0 B0 C0
11 21 31 41 51 61 71 81 91 A1 B1 C1
12 22 32 42 52 62 72 82 92 A2 B2 C2
13 23 33 43 53 63 73 83 93 A3 B3 C3
14 24 34 44 54 64 74 84 94 A4 B4 C4
15 25 35 45 55 65 75 85 95 A5 B5 C5
16 26 36 46 56 66 76 86 96 A6 B6 C6
17 27 37 47 57 67 77 87 97 A7 B7 C7
18 28 38 48 58 68 78 88 98 A8 B8 C8
19 29 39 49 59 69 79 89 99 A9 B9 C9

然后在大文件上运行第一个 block 看起来像:

$ time awk -v chunk_start=1 -v chunk_size=1000 -f et.awk tenk.txt  > tenk-transpose.txt

real    1m7.899s
user    1m5.173s
sys     0m2.552s

将下一个 chunk_start 设置为 1001 等十次(当然,还要将 >>> 附加到输出中)最终应该会给你完整的转置结果。

关于awk - 内存高效转置 - Awk,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29081539/

相关文章:

regex - 必要时使用正则表达式向 csv 文件添加逗号

bash - 如何使用 BASH 脚本的 AWK 生成给定开始日期和结束日期的日期序列?

awk - awk中如何剪切字段

excel - 如何将部分 Excel 数据转换为列以获得所需的输出?

MYSQL - 选择4个随机行并将它们转置为插入语句的列

visual-studio - Visual Studio CTRL + SHIFT + T转置-它是做什么的?

bash - 如何在 shell 脚本中从 YML 中删除子 block ?

linux - 操作第一个字段,然后使用 awk 打印 csv 文件的其余行

list - 在没有 Maybe 的情况下在 Elm 中转置

c# - 如何转置矩阵?