有没有办法将 HEREDOC 用于 Bash 和 Zsh,并且能够使用参数?

有没有办法将 HEREDOC 用于 Bash 和 Zsh,并且能够使用参数?

Bash 和 Zsh 的 HEREDOC 似乎就像一个文件,而不是字符串,如果我希望做类似的事情

foo() {
    ruby << 'EOF'
        3.times do
            puts "Ruby is getting the argument #{ARGV[0]}"
        end
EOF 
}

有没有办法将参数传递给 Ruby 程序?最好不要将 插入$1到 Ruby 代码中,这就是我使用'EOF'而不是 的原因EOF,因为插入到 Ruby 代码中可能会很混乱。

有一种方法可以将 HEREDOC 作为字符串使用,方法如下:

foo() {
    ruby -e "$(cat << 'EOF'
        3.times do
            puts "Ruby is getting the argument #{ARGV[0]}"
        end
EOF
)" $1    
}

并且它有效(虽然有点hacky)。但是有没有办法使用 HEREDOC 通常的方式将其视为文件并能够向 Ruby 提供参数?

答案1

在带有 的系统上,您始终可以执行以下操作:/dev/fd/n

foo() {
  ruby /dev/fd/3 "$@" 3<< 'EOF'
    3.times do
      puts "Ruby is getting the argument #{ARGV[0]}"
    end
EOF
}

这里使用高于 2 的 fd,因此您的ruby脚本仍然可以使用 stdin/stdout/stderr 而不受影响。

如果您的系统是少数仍然不支持的系统之一,您可以执行以下操作:/dev/fd/n

foo() {
  ruby - "$@" << 'EOF'
    3.times do
      puts "Ruby is getting the argument #{ARGV[0]}"
    end
EOF
}

ruby其本身解释-为含义标准输入)。

但这意味着ruby内联脚本的标准输入现在是heredoc,因此该脚本将无法通过原始标准输入查询用户,除非您以其他方式提供该流。

Heredoc 是 70 年代末随 Bourne shell 附带的一项功能。它是一个重定向运算符,意味着将某些文件描述符(0默认情况下又称为 stdin)重定向到某些固定内容。最初,这是通过临时文件实现的,尽管一些 shell,包括 bash5.1+ 使用(有时)管道。

另请注意, in 与 in或类似,但与 in , 不同,您确实需要标记选项的结尾,否则如果以 开头,它将被视为 的选项。ruby -e code -- arbitrary-argumentsed -e codeperl -e codesh -c codepython -c code--arbitrary-argument-ruby

我们不需要它在nor中,因为在非选项参数or之后不需要选项。ruby /dev/fd/3 arbitrary-argumentruby - arbitrary-argument-/dev/fd/3

答案2

您可能想使用此语法,只需将 ruby​​ 程序包含在单引号中即可:

#!/bin/sh -

foo() {
    ruby -e '
        3.times do
            puts "Ruby is getting the argument #{ARGV[0]}"
        end
    ' -- "$@"
}

foo test-arg

类似于python -c 'command'or awk ''orsh -c 'command'等​​。后面是参数。在引号内,您可以使用代码编写多行文本。 (--定义选项的结尾很重要,例如对于以下参数以 开头的情况-,另请参阅此回答

这实际上是 ruby​​ 命令的 shell 包装器,您可以使用 shell 来过滤输入、处理输出、调用更多程序等。这里您可以看到有关引用参数的更多信息,我已替换为 来"$@"引用所有参数,从 shell 脚本传递到 ruby​​ 命令,您也可以使用等$1$2

当然,需要注意单引号。如果可以的话,请避开它​​们。使用它们的方法可能不止一种,例如在两个单引号字符串之间\047插入或插入。\'例子:

$ ruby -e 'puts "Ruby\047s #{ARGV[0]}"' great
Ruby's great
$ ruby -e 'puts "Ruby'\''s #{ARGV[0]}"' great
Ruby's great

这里更多关于引用的内容。

答案3

参数“-”表示“标准输入”。

foo() {
  ruby - "$@" << 'EOF'
    3.times do
      puts "Ruby is getting the argument #{ARGV[0]}"
    end
EOF
}
$ foo bar
Ruby is getting the argument bar
Ruby is getting the argument bar
Ruby is getting the argument bar
$ 

相关内容