AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 1176231
Accepted
user2413
user2413
Asked: 2019-09-24 22:26:48 +0800 CST2019-09-24 22:26:48 +0800 CST 2019-09-24 22:26:48 +0800 CST

AWK:将行数*追加到模式的下一个*出现(在一个巨大的文件中)

  • 772

考虑这个文件:

#!/usr/bin/env bash
cat > example_file.txt <<EOL
TITLE something
some data
some data
some data
TITLE something else
some other data
TITLE some more
some other data
some other data
some other data
TITLE extra info
some more data
some more data
EOL

我需要添加一个新列:

  • 计算行数,
  • 在发生 , 后返回/^TITLE/1
  • 从文件的底部开始向上工作,

基本上,结果应该如下所示:

TITLE something,4
some data,3
some data,2
some data,1
TITLE something else,2
some other data,1
TITLE some more,4
some other data,3
some other data,2
some other data,1
TITLE extra info,3
some more data,2
some more data,1

PS你可以假设:

  • 文件总是以匹配行开头/^TITLE/
  • 文件总是以不匹配的行结尾/^TITLE/
  • 没有连续的两行匹配/^TITLE/

编辑:

到目前为止的结果

在一个 100MB 的文件上:

@亚罗姆

time tac trial.txt | awk 'BEGIN{x=0} {x++;{if ($1 !~/^pattern/) printf "%s,%s\n",$0,x;else if ($1 ~/^pattern/) {printf "%s,%s\n",$0,x;x=0}}}' | tac > trial2.txt
real    0m0,896s

@bac0n

 time awk '{ a[i++]=$0 } END { while (i--) { a[i]=a[i] "," ++j; if (a[i] ~ /^pattern/) { j=0 } }; for (i=0; i<NR; i++) { print a[i] } }' trial.txt > trial2.txt
real    0m0,830s

@奥利夫:

time awk -v RS='^pattern' -v FS='\n' '
{
  for(i=NF-1;i>0;i--) 
    printf "%s,%d\n",$i,i; 
    printf RT
}' trial.txt > trial2.txt

real    0m2,343s

@steeldriver

 time awk -vRS='\n(^pattern|$)' -F'\n' -vOFS=, '
   NR>1 {$1 = "^pattern" $1} 
   {for(i=1;i<=NF;i++) print $i, NF-i+1}
 ' trial.txt > trial2.txt
real    0m1,889s

使用 mawk 而不是 awk,我得到:

mawk: program limit exceeded: maximum number of fields size=32767
awk
  • 4 4 个回答
  • 254 Views

4 个回答

  • Voted
  1. Yaron
    2019-09-24T23:37:29+08:002019-09-24T23:37:29+08:00

    我设法编译了以下单行:

    tac so_count.txt | awk 'BEGIN{x=0} {x++;{if ($1 != "TITLE") printf "%s,%s\n",$0,x;else if ($1 == "TITLE") {printf "%s,%s\n",$0,x;x=0}}}' | tac
    

    我再解释一下:

    • tac- 颠倒行的顺序(反向猫)。
    • awk- 如果第一列没有TITLE推进计数器,如果TITLE打印当前计数并重置回 0。
    • tac- 反过来。

    结果:

    TITLE something,4
    DATA some data,3
    DATA some data,2
    DATA some data,1
    TITLE something else,2
    DATA some other data,1
    TITLE some more,4
    DATA some other data,3
    DATA some other data,2
    DATA some other data,1
    TITLE extra info,3
    DATA some more data,2
    DATA some more data,1
    

    祝你好运!

    • 2
  2. oliv
    2019-09-25T03:53:57+08:002019-09-25T03:53:57+08:00

    使用 awk:

    awk -v RS='TITLE ' -v FS='\n' '
    {
      for(i=NF-1;i>0;i--) 
        printf "%s,%d\n",$i,i; 
        printf RT
    }' file
    

    这依赖于记录分隔符RS和字段分隔符FS,它们设置为将正确的起始值设置为 counter i。

    唯一的语句打印每个字段,其中包含与RT关联的计数器和记录终止符RS。

    该解决方案的优点是只解析文件一次,并且不需要将整个文件放入内存中。

    • 2
  3. Best Answer
    user986805
    2019-09-25T01:16:45+08:002019-09-25T01:16:45+08:00

    例子.awk

    #!/bin/awk -f
    
    { a[i++]=$0 } END {
        while (i--) {
            a[i]=a[i] "," ++j
            if (a[i] ~ /^TITLE/) { j=0 }
        }
        for (i in a) { print a[i] }
    }
    

    例子

    awk -f example.awk example.txt
    

    输出

    TITLE something,4
    DATA some data,3
    DATA some data,2
    DATA some data,1
    TITLE something else,2
    DATA some other data,1
    TITLE some more,4
    DATA some other data,3
    DATA some other data,2
    DATA some other data,1
    TITLE extra info,3
    DATA some more data,2
    DATA some more data,1
    
    • 1
  4. steeldriver
    2019-09-25T04:01:54+08:002019-09-25T04:01:54+08:00

    您可以将每个块视为一条记录,将每一行视为一个字段 - 这样,您可以在不反转文件或将多个块加载到内存中的情况下减少每个块的计数。

    因为您的块是由页眉而不是页脚描述的,所以需要一些技巧来处理第一个和最后一个记录。我能想到的最好的是:

    awk -vRS='\n(TITLE|$)' -F'\n' -vOFS=, '
      NR>1 {$1 = "TITLE" $1} # replace the RS that got stripped off
      {for(i=1;i<=NF;i++) print $i, NF-i+1}
    ' example_file.txt
    

    gawk这在和中都应该有效mawk。我怀疑它会在较低开销的情况下运行得更快mawk;gawk如果将语言环境设置为 C/POSIX,速度可能相当,即LC_ALL=C awk '...'

    • 1

相关问题

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve