Bash 및 Zsh와 함께 HEREDOC을 사용하고 매개변수를 사용할 수 있는 방법이 있습니까?

Bash 및 Zsh와 함께 HEREDOC을 사용하고 매개변수를 사용할 수 있는 방법이 있습니까?

Bash와 Zsh의 HEREDOC은 다음과 같은 작업을 수행하려는 경우 문자열이 아닌 파일처럼 작동하는 것 같습니다.

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

Ruby 프로그램에 매개변수를 전달하는 방법이 있나요? $1Ruby 코드에 삽입하지 않는 것이 더 좋으며 , Ruby 코드에 삽입하면 지저분해질 수 있기 때문에 'EOF'대신 를 사용합니다 .EOF

다음과 같이 HEREDOC을 문자열로 사용하는 방법이 있습니다.

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

그리고 그것은 작동합니다(약간 해킹되기는 하지만). 하지만 일반적인 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은 1970년대 후반 Bourne 쉘과 함께 제공된 기능입니다. 이는 0일부 파일 설명자(기본적으로 stdin이라고도 함)를 일부 고정 콘텐츠로 리디렉션하는 것을 의미하는 리디렉션 연산자입니다 . bash5.1+를 포함한 일부 쉘은 (때때로) 파이프를 사용하지만 원래 이는 임시 파일을 통해 구현되었습니다.

또한 in 은 in 또는 와 유사하지만 in 과 달리 옵션의 끝을 표시해야 합니다. 그렇지 않으면 in 으로 시작하면 옵션으로 처리됩니다.ruby -e code -- arbitrary-argumentsed -e codeperl -e codesh -c codepython -c code--arbitrary-argument-ruby

옵션이 아닌 인수 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'또는 awk ''등과 유사합니다 sh -c 'command'. 다음은 매개변수입니다. 따옴표 안에 코드를 사용하여 여러 줄의 텍스트를 작성할 수 있습니다. ( --예를 들어 로 시작하는 다음 인수의 경우 옵션의 끝을 정의하는 것이 중요합니다. -이 항목도 참조하세요.답변)

이는 본질적으로 Ruby 명령을 둘러싼 쉘 래퍼이며, 쉘을 사용하여 입력 필터링, 출력 처리, 더 많은 프로그램 호출 등을 수행할 수 있습니다.여기매개변수 인용에 대한 자세한 내용을 볼 수 있으며, 쉘 스크립트에서 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
$ 

관련 정보