【问题标题】:How can I provide the $INPUT_RECORD_SEPARATOR to ruby -n -e?如何将 $INPUT_RECORD_SEPARATOR 提供给 ruby​​ -n -e?
【发布时间】:2016-02-02 14:02:21
【问题描述】:

我想使用 Ruby 的 $INPUT_RECORD_SEPARATOR 又名 $/ 来操作制表符分隔的文件。

输入文件如下所示(大体简化):

a   b   c

(值由制表符分隔)。

我想得到以下输出:

a---
b---
c---

我可以通过使用ruby -e 并设置$INPUT_RECORD_SEPARATOR 别名$/ 轻松实现这一点:

cat bla.txt | ruby -e '$/ = "\t"; ARGF.each {|line| puts line.chop + "---" }'

这行得通,但我真正想要的是:

cat bla.txt | ruby -n -e '$/ = "\t"; puts $_.chop + "---" '

但是,这会打印:

a       b       c---

显然,它没有使用提供的分隔符——大概是因为它在设置分隔符之前已经读取了第一行。我尝试将其作为环境变量提供:

cat bla.txt | $/="\n" ruby -n -e 'puts $_.chop + "---" '

但这会使 shell 感到困惑 - 它试图将 $/ 解释为命令(我还尝试用一个、两个、三个或四个反斜杠转义 $,但都无济于事)。

那么如何将 $/ 与 ruby​​ -n -e 结合使用?

【问题讨论】:

    标签: ruby command-line io


    【解决方案1】:

    使用-0 选项:

    cat bla.txt | ruby -011 -n -e 'puts $_.chop + "---" '
    a---
    b---
    c---
    

    -0[ 八进制] 将默认记录分隔符 ($/) 设置为八进制。如果未指定八进制,则默认为 \0。

    标签的 ascii 代码为 9,八进制为 11。因此-011

    【讨论】:

    • 一开始无法正常工作,因为我的 .vimrc 文件中有 set expandtabs.. 只是一个注释:/
    • 完美,正是我想要的。
    【解决方案2】:

    使用 BEGIN 块,在 Ruby 开始循环遍历行之前处理该块:

    $ echo "foo\tbar\tbaz" | \
    >   ruby -n -e 'BEGIN { $/ = "\t" }; puts $_.chop + "---"'
    foo---
    bar---
    baz---
    

    或者,更易读:

    #!/usr/bin/env ruby -n
    BEGIN {
      $/ = "\t"
    }
    
    puts $_.chop + "---"
    

    然后:

    $ chmod u+x script.rb
    $ echo "foo\tbar\tbaz" | ./script.rb
    foo---
    bar---
    baz---
    

    如果这不仅仅是一个一次性脚本(即其他人可能会使用它),那么使用参数或环境变量使其可配置可能是值得的,例如$/ = ENV['IFS'] || "\t".

    【讨论】:

    • 不错(+1)。我接受了@cozyconemotel 的答案,因为它更紧凑,恕我直言,因此更适合一次性脚本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 2015-11-12
    • 2016-04-18
    • 2017-02-03
    • 2018-01-10
    • 2019-09-04
    • 1970-01-01
    相关资源
    最近更新 更多