【问题标题】:Printing verbose progress from sed and awk从 sed 和 awk 打印详细进度
【发布时间】:2012-04-07 16:52:23
【问题描述】:

程序sedawk 通常会安静地工作。有什么方法可以让这些程序说明它们在做什么?

【问题讨论】:

    标签: sed awk


    【解决方案1】:

    这是基于波东的回答。以下代码将“ll”替换为“zz”,创建备份文件,显示新文本,并将更改写入文件。

    $ echo hello > test
    $ sed -e 's/ll/zz/;w /dev/stdout' -i .backup test
    hezzo
    $ cat test
    hezzo
    $ cat test.backup 
    hello
    

    【讨论】:

    • 在较新的 sed 版本中,如果省略 w 之前的分号,则 w 成为“s”sed 命令的参数,并且只有更改写入 /dev/stdout,对我来说是比写整个文件更有用
    • 2020 : g 必须为全局替换添加 -> sed -i 's/oldtext/newtext/gw /dev/stdout '
    【解决方案2】:

    假设您将 sed 输出通过管道传输到文件,您可以使用 tail 命令(在另一个终端中)不断查看文件末尾;这样您就可以看到进度。

    tail -f output_from_sed.txt
    

    【讨论】:

      【解决方案3】:

      这可能对你有用(对于 sed):

      sed -i 's/foo/bar/;w /dev/stdout' files*
      

      这将在应用更改后打印文件的内容。

      【讨论】:

      • 对我来说,原始命令中的 -i 在 OS X 上不起作用。是否缺少 -e?
      • Paul 的评论:在 OS X 上使用 sed 的工作示例:$ echo hello > test $ sed -e 's/ll/zz/;w /dev/stdout' -i .backup test hezzo $ cat test hezzo $ cat test.backup hello
      • Paul:Mac OS X 使用 BSD 版本的 sed,它在某些方面与 Linux 系统上常见的 GNU 版本不同。对于 BSD sed,您必须始终为 -i 指定 some 扩展名,而 GNU sed 不会将任何内容解释为空字符串。因此,与 GNU sed 的 sed -i 等效的 BSD sed 就是 sed -i ''。 StuartLC 的示例在任一版本上的工作方式都相同,因为他没有在适当的位置编辑文件(即,他使用的是非零长度扩展名,因此不会遇到这个小差异)。
      【解决方案4】:

      您总是可以告诉 awk 打印输入记录,即

       awk '{ 
             print "#dbg:$0="$0 
             # do more stuff
             print $1
             # or make it conditional
             if ($0 ~ /specialRegEx/){
                    print "#dbg:$0="$0 
             }
            }' infile
      

      使用 sed,您可以使用 'p' cmd 打印每一行,但默认是打印每一行。类似的东西

       sed 'p
            # also "=" prints line # being processed
            =
            /specialRegEx/{
              s/xxx/yyy/
              p
            }' infile
      

      我希望这会有所帮助。

      【讨论】:

        【解决方案5】:

        如果您要将sedawk 的输出重定向到文件(而不是就地修改文件),您可以试一试pv(“管道查看器”):

        sed -e '...' input.txt | pv > output.txt
        

        您可以使用pv -l 使其以书面形式报告进度。进度状态打印到stderr,而实际数据从stdinstdout

        【讨论】:

          【解决方案6】:

          如果您使用的是 Linux,您可以通过查看 /proc/<pid>/fdinfo 查看处理大文件的进程的进度。每个打开的文件描述符都有一个条目,如果您对条目进行分类,它们会向您显示文件描述符的读/写位置。所以你可以看到你在文件中是1123456字节。打开文件的路径名在另一个区域:/proc/<pid>/fd,表示为符号链接。

          在查看之前,我通常会在进程中附加一个stracestrace -p <pid>。您可以使用它来查看进程正在执行的系统调用:文件读取和写入,以及brkmmap 的内存分配。

          【讨论】:

          • 为方便起见:ps ax | grep foo 其中foo 是有问题的程序的名称,可用于查找上面使用的进程ID。
          【解决方案7】:

          这可能不是您正在寻找的,但它可能对其他人有所帮助。 FWIW:
          gawk -W dump-variables=/tmp/awk.log
          将脚本末尾的变量值转储到日志文件中。

          【讨论】:

            【解决方案8】:

            这里的“正确”答案是

            pv myfile.txt | sed ...
            

            Eduardo Ivanec 的回答很接近,但是通过使用管道查看器 (pv) 进行实际管道,您可以了解文件中的进度(以百分比表示,包括 M/sec 等重要统计数据、总数据等)。

            pvcat 一样工作(读取文件并将其直接导出到stdout,或者在管道输入的情况下,它是stdinstdout 之间的桥梁。

            重要的是,由于pv 是一个“透明管道进程”,stdout 被用于中继数据。所以进度报告是通过stderr上报的。

            【讨论】:

            • 请注意,这不适用于就地替换...(AFAIK)
            【解决方案9】:

            awk 输出到/dev/stderr

            我有时会处理涉及 4 行块 (FASTQ) 的大型数据文件,因此我经常使用stderr 定期输出状态消息(每 100K 行)。这是一个基本模板:

            #!/usr/bin/awk -f
            
            BEGIN {
                # Check for any expected input variables
            
                # Status
                print "[INFO] Initiating processing..." > "/dev/stderr";
            }
            {
                # Do stuff
            
                # Status
                if (NR % 400000 == 0) {
                    printf("[INFO] %d reads processed\n", NR/4) > "/dev/stderr";
                }
            }
            END {
                # Final status
                printf("[INFO] %d total reads\n", NR/4) > "/dev/stderr";
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-06-26
              • 2015-04-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-04-13
              相关资源
              最近更新 更多