什么是Awk的FNR == NR的Ruby等价物?

时间:2017-07-06 00:03:33

标签: ruby awk command-line

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

在awk中,通常有:

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

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

Ruby拥有令人难以置信的文本处理语言。 Ruby有$.等同于awk的NR什么相当于FNR

1 个答案:

答案 0 :(得分:2)

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等