【问题标题】:What is the Ruby equivalent of Awk's FNR==NR?Awk 的 FNR==NR 的 Ruby 等价物是什么?
【发布时间】:2017-07-06 00:03:33
【问题描述】:

Awk 具有内置变量FNRNR,用于从当前文件读取的记录数(通常为行数)和总数。

在 awk 中,通常有:

$ awk 'FNR==NR {first file lines; next } {process remaining lines } f1 f2

通常,f1 包含确定如何处理剩余文件的值。 (关键词、行号等)

Ruby 具有出色的文本处理语言的特质。 Ruby 有 $. 相当于 awk 的 NR 什么相当于 FNR

【问题讨论】:

    标签: ruby awk command-line


    【解决方案1】:

    Ruby 具有ARGF stream(如果您想感受 Perly,则别名为 $<),它可以读取 STDIN 或从命令行打开文件。与awk 相同的行为:

    $ awk '{print FNR,NR,$0}' f1 f2
    1 1 line 1
    2 2 line 2
    3 3 line 3
    1 4 LINE 1
    2 5 LINE 2
    
    $ ruby -lane 'puts [ARGF.file.lineno, $., $_].join(" ")' f1 f2 
    1 1 line 1
    2 2 line 2
    3 3 line 3
    1 4 LINE 1
    2 5 LINE 2
    

    如果您想同时读取STDIN 和文件,您可以使用- 作为文件占位符:

    $ echo '123' | awk '1' - <(echo 456)
    123
    456
    $ echo '123' | awk '1' <(echo 456) -
    456
    123
    
    $ echo '123' | ruby -lane 'puts $_' - <(echo 456)
    123
    456
    $ echo '123' | ruby -lane 'puts $_' <(echo 456) -
    456
    123
    

    一些对应的变量:

    ╔═════════╦═══════════════════╦═════════════════════════════════════════╗
    ║   awk   ║       ruby        ║                 comment                 ║
    ╠═════════╬═══════════════════╬═════════════════════════════════════════╣
    ║ $0      ║ $_                ║ unsplit record (line usually)           ║
    ║ NF      ║ $F.length         ║ Number of fields from autosplit         ║
    ║ FNR     ║ ARGF.file.lineno  ║ Number records read from current source ║
    ║ NR      ║ ARGF.lineno or $. ║ Total number of records so far          ║
    ║ (magic) ║ ARGF or $<        ║ stream from either STDIN or a file      ║
    ║ $1..$NF ║ $F[0]..$F[-1]     ║ First to last field from autosplit      ║
    ║ FS      ║ $;                ║ Input field separator                   ║
    ║ RS      ║ $/                ║ Input record separator                  ║
    ╚═════════╩═══════════════════╩═════════════════════════════════════════╝  
    

    因此,如果您在f1 中有一个行号列表和一个您想用这些行号索引的文本文件(您将使用awksed 来执行此操作),则可以使用 Ruby .

    给定:

    $ echo "1
    2
    44
    2017" >f1
    $ seq 10000 | awk '{print "Line", $1}' >f2
    

    awk 你会这样做:

    $ awk 'FNR==NR{ln[$1]; next} 
           FNR in ln'    f1 f2
    

    在 Ruby 中你可以这样做:

    $ ruby -lane 'BEGIN{h=Hash.new}
                  if $<.file.lineno == $<.lineno
                     h[$F[0].to_i]=true
                     next
                  end
                  puts $_ if h[$<.file.lineno]' f1 f2
    

    两个打印:

    Line 1
    Line 2
    Line 44
    Line 2017
    

    本示例的 awk 版本大约快 5 倍(go awk),但 Ruby 版本可以轻松支持 awk 无法支持的输入,例如 JSON、XML、复杂 csv 等

    【讨论】:

    猜你喜欢
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    • 2010-11-01
    相关资源
    最近更新 更多