哪个AWK程序可以执行此操作?

哪个AWK程序可以执行此操作?,awk,fish,Awk,Fish,给定一个包含如下结构的文件,其中的字段由SP或HT分隔 4 5 6 2 9 8 4 8 m d 6 7 9 5 4 g t 7 4 2 4 2 5 3 h 5 6 2 5 s 3 4 r 5 7 1 2 2 4 1 4 1 9 0 5 6 d f x c a 2 3 4 5 9 0 0 3 2 1 4 q w 我需要哪个AWK程序才能获得以下输出 4 5 m d t 7 h 5 r 5 4 1 x c 0 0 6 2 6 7 4 2 6 2

给定一个包含如下结构的文件,其中的字段由SP或HT分隔

4 5 6 2 9 8 4 8
m d 6 7 9 5 4 g
t 7 4 2 4 2 5 3
h 5 6 2 5 s 3 4
r 5 7 1 2 2 4 1
4 1 9 0 5 6 d f
x c a 2 3 4 5 9
0 0 3 2 1 4 q w
我需要哪个AWK程序才能获得以下输出

  4 5
  m d
  t 7
  h 5
  r 5
  4 1
  x c
  0 0
  6 2
  6 7
  4 2
  6 2
  7 1
  9 0
  a 2
  3 2
  9 8
  9 5
  4 2
  5 s
  2 2
  5 6
  3 4
  1 4
  4 8
  4 g
  5 3
  3 4
  4 1
  d f
  5 9
  q w
提前感谢您的帮助

附言

请记住

我的输入文件比这个问题中描述的文件大得多

我的计算机科学技能严重受限

这项任务是强加给我的

使用以下Perl脚本:

perl -lane '
push @rows, [@F];
END {
    my $delim = "\t";
    my $cols_per_group = 2;
    my $col_start = 0;
    while ( 1 ) {
         for my $row ( @rows ) {
             print join $delim, @{$row}[ $col_start .. ($col_start + $cols_per_group - 1) ];
         }
         $col_start += $cols_per_group;
         last if ($col_start + $cols_per_group - 1) > $#F;
    } 
}
' in_file > out_file
Perl one liner使用以下命令行标志: -e:告诉Perl在线查找代码,而不是在文件中。 -n:一次循环输入一行,默认情况下将其分配给$。 -l:在行内执行代码之前,默认情况下在*NIX上去掉\n输入行分隔符,并在打印时附加它。 -a:将$拆分为空格上的数组@F或-F选项中指定的正则表达式上的数组@F

此脚本将文件读入内存。这对于大多数现代计算机和所讨论的文件大小来说都是可以的

每一行都在空白处拆分,使用-F'\t'作为制表符分隔到数组@F中。每一行对该数组的引用都存储为数组@rows中的元素。读取文件后,脚本的结尾在end{…}块中,文件的内容以列组的形式打印,每个组的列数为$cols_。列由$delim分隔

另见:

awk-Vn=4' 函数joinstart、end、result、i{ 对于i=start;i output.file ________________________________________________________ 执行时间为3.62秒 usr时间3.49秒0.24毫秒3.49秒 系统时间0.11秒1.96毫秒0.11秒 $wc output.file 2097152 8388608 16777216 output.file 帖木儿的perl:

$time perl-lan columnize.pl input.file>output.file ________________________________________________________ 执行时间为3.25秒 usr时间2.97秒0.16毫秒2.97秒 系统时间0.27秒2.87毫秒0.27秒 拉文德awk

$time awk-f columnize.ravinder input.file>output.file ________________________________________________________ 执行时间为4.01秒 usr时间3.84秒0.18毫秒3.84秒 系统时间0.15秒3.75毫秒0.14秒 kvantour的awk,第一版

$time awk-f columnize.kvantour-v n=4 input.file>output.file ________________________________________________________ 执行时间为3.84秒 usr时间3.71秒166.00微秒3.71秒 系统时间0.11秒1326.00微秒0.11秒 kvantour的第二个awk版本:Crtl-C在几分钟后中断

$time awk-f columnize.kvantour2-v n=4 input.file>output.file ^C ________________________________________________________ 执行时间为260.80秒 usr时间257.39秒0.13毫秒257.39秒 系统时间1.68秒2.72毫秒1.67秒 $wc output.file 9728 38912 77824 output.file $0=a[j]行非常昂贵,因为它每次都必须将字符串解析为字段

道格巨蟒

$timeout 60s fish-c'time python3 columnize.py input.file 4>output.file' […60秒后…] $wc output.file 2049 8196 16392 output.file 另一个有趣的数据点:使用不同的awk实现。我在Mac上,通过自制安装了GNU awk和mawk

列多行少

$time gawk-f columnize.awk-v n=4 input.file>output.file ________________________________________________________ 执行时间为3.78秒 usr时间3.62秒174.00微秒3.62秒 系统时间0.13秒1259.00微秒0.13秒 $time/usr/bin/awk-f columnize.awk-v n=4 input.file>output.file ________________________________________________________ 执行时间为17.73秒 usr时间14.95秒0.20毫秒14.95秒 系统时间2.72秒3.45毫秒2.71秒 $time mawk-f columnize.awk-v n=4 input.file>output.file ________________________________________________________ 执行时间为2.01秒 usr时间1892.31毫秒0.11毫秒1892.21毫秒 系统时间95.14毫秒2.17毫秒92.97毫秒 由于行多,列少,这个测试在MacBookPro、6核Intel cpu、16GB ram上花费了半个多小时

$time mawk-f columnize.awk-v n=4 input.file>output.file ________________________________________________________ 在32.30分钟内执行 usr时间23.58分钟0.15毫秒23.58分钟 系统时间8.63分钟2.52毫秒8.63分钟
请您尝试以下,书面和测试只显示样本在GNU awk


既然我们都喜欢awk,下面是另一个:

awk -v n=2 '{for(i=1;i<=NF;++i) { j=int((i-1)/n); a[j] = a[j] $i (i%n==0 || i==NF ?ORS:OFS) }}
            END{for(j=0;j<=int(NF/n);j++) printf "%s", a[j]}'
注意:后者似乎只对少量列有效。这是因为 用$0=a[j]重新拆分常数。由于字段数量很大,拆分需要更多的时间。该系统的复杂性为ONF^2*NR

最后一种替代方法:第一种解决方案对于大量列和少量行是快速的,而第二种解决方案对于少量列和大量行是快速的。下面是一个最终版本,它不是很快,但是很稳定,并且为转置的文件生成相同的时间

awk -v n=2 '{ for(i=1;i<=NF;i+=n) {
                s=""
                for(k=0;k<n&&(i+k<=NF);++k) 
                   s=s  $(i+k)  ((i+k==NF || ((i+k) % n == 0)) ? "ORS" : OFS);
                a[i,NR]=s 
             }
            }
            END{for(i=1;i<=NF;i+=n)for(j=1;j<=NR;++j) printf "%s",a[i,j]}' file

我的旧答案如下,不再适用

您可以将此awk用于可能有数百万行或数百万列的文件。基本方案是将所有值吸纳到单个数组中,然后在末尾使用索引算法和嵌套循环以获得正确的顺序:

$ cat col.awk
{
    for (i=1; i<=NF; i++) {
        vals[++numVals] = $i
        }
    }
    END {
    for(col_offset=0; col_offset + cols <= NF; col_offset+=cols) {
        for (i=1; i<=numVals; i+=NF) {
            for(j=0; j<cols; j++) {
                printf "%s%s", vals[i+j+col_offset], (j<cols-1 ? FS : ORS)
                }
        } 
    }
}

$ awk -f col.awk -v cols=2 file
4 5
m d
t 7
h 5
...
3 4
4 1
d f
5 9
q w
这是违反直觉的,但与吞咽整个东西相比,多次读取一个文件通常要快得多,效率也要高得多——如果吞咽会导致更大数据的坏结果

那么,与本文中的一个AWK相比,它的性能如何呢?让我们计时

根据您的示例,内存中的awk可能会更快:

$ cat file
4 5 6 2 9 8 4 8
m d 6 7 9 5 4 g
t 7 4 2 4 2 5 3
h 5 6 2 5 s 3 4
r 5 7 1 2 2 4 1
4 1 9 0 5 6 d f
x c a 2 3 4 5 9
0 0 3 2 1 4 q w

$ time python pys.py file 2 >file2
real    0m0.027s
user    0m0.009s
sys 0m0.016s

$ time awk -v n=2 '{for(i=1;i<=NF;++i) { 
  j=int((i-1)/n); a[j] = a[j] $i (i%n==0 || i==NF ?ORS:OFS) }}
  END{for(j=0;j<=int(NF/n);j++) printf "%s", a[j]}' file >file3
real    0m0.009s
user    0m0.003s
sys 0m0.003s
以同样的方式重新运行这些计时,您将得到:

#python
real    0m0.061s
user    0m0.044s
sys 0m0.015s

# awk
real    0m0.050s
user    0m0.043s
sys 0m0.004s
大约在同一时间。。。现在将原始文件乘以100000,使文件变大,得到800000行和12MB,然后再次运行计时:

# python
real    0m3.475s
user    0m3.434s
sys 0m0.038s

#awk
real    22m45.118s
user    16m40.221s
sys 6m4.652s

对于12MB文件,内存中的方法基本上无法使用,因为此计算机上的VM系统需要进行大规模磁盘交换以管理特定类型的内存分配。可能是2级或更差。这台计算机是2019 Mac Pro 16核Xeon,内存为192GB,因此它不是硬件…

欢迎使用so,因此强烈鼓励问题的原始海报在问题中添加他们各自的努力或正确或错误,因此请在您的问题中添加相同的努力,谢谢。字段分隔符-制表符或空白是什么?多少列:8或更多?是否预先知道列数?@TimurShtatland有时字段分隔符都是TAB HT,而在其他一些文件中,字段分隔符都是空白SP,有100多万列,但行始终是8。我也希望能够选择4、8、16、32、64等一组的输出,不一定是示例中的2人小组。@RavinderSingh13我第一次接触AWK是在昨天,我刚刚下载了Arnold Robbins几小时前编写的有效的AWK编程:通用文本处理和模式匹配……我是一所学校的热质传递实验室讲师……我真的需要这个解决方案,当然我也需要将在我与我的新朋友搏斗时进行尝试book@two_big_a_pac根据您的评论更新了答案。即使在较大的文件上,这也很快。美好的非常感谢,这正是我想要的输出形式。我已经用同样的例子在bash中测试了它,我希望明天早上第一件事就是在办公室用一个真正的数据集再次测试它。该程序正在工作……现在注意:在较大的文件上,这会变得非常慢。尝试制作12M示例并尝试此脚本。@dawg这与12MB的脚本非常接近,但您的python速度更快:python:4.72s,awk:5.15s您的第二个脚本速度明显更快!干得好!!注意:对于较大的文件,这会变得非常慢。尝试制作示例12M并尝试此脚本。@dawg,感谢您的警告,我还没有用大文件对其进行测试,这就是为什么我只使用显示的示例编写Check,如果可以的话,稍后将尝试添加另一个解决方案,谢谢。重新阅读评论,我的警告可能为时过早。awk处理数百万行数据的速度非常慢,但他说他有数百万列,总共有8行。不同的分析。好奇:请用数百万行和8列重试基准测试?欢迎你这么做,但这不是OP的场景。问题是日期的形状。数百万行x 8 vs数百万列x 8。如果你有数百万行,除了kvantour的第二行,这些AWK都非常慢。如果你看到数以百万计的列,那么python编写的速度非常慢。@dawg,我确实尝试过几次运行,输入文件将几列转换成了许多行,我可以确认你的观察结果:python速度很快,我的awk速度很慢
$ cat file
4 5 6 2 9 8 4 8
m d 6 7 9 5 4 g
t 7 4 2 4 2 5 3
h 5 6 2 5 s 3 4
r 5 7 1 2 2 4 1
4 1 9 0 5 6 d f
x c a 2 3 4 5 9
0 0 3 2 1 4 q w

$ time python pys.py file 2 >file2
real    0m0.027s
user    0m0.009s
sys 0m0.016s

$ time awk -v n=2 '{for(i=1;i<=NF;++i) { 
  j=int((i-1)/n); a[j] = a[j] $i (i%n==0 || i==NF ?ORS:OFS) }}
  END{for(j=0;j<=int(NF/n);j++) printf "%s", a[j]}' file >file3
real    0m0.009s
user    0m0.003s
sys 0m0.003s
txt='''\
4 5 6 2 9 8 4 8
m d 6 7 9 5 4 g
t 7 4 2 4 2 5 3
h 5 6 2 5 s 3 4
r 5 7 1 2 2 4 1
4 1 9 0 5 6 d f
x c a 2 3 4 5 9
0 0 3 2 1 4 q w
'''

with open('/tmp/file', 'w') as f:
    f.write(txt*1000)              # change the 1000 to the multiple desired

# file will have 8000 lines and about 125KB
#python
real    0m0.061s
user    0m0.044s
sys 0m0.015s

# awk
real    0m0.050s
user    0m0.043s
sys 0m0.004s
# python
real    0m3.475s
user    0m3.434s
sys 0m0.038s

#awk
real    22m45.118s
user    16m40.221s
sys 6m4.652s