Fish Shell - 값 배열을 확인하는 스위치 문을 생성하기 위한 구문

Fish Shell - 값 배열을 확인하는 스위치 문을 생성하기 위한 구문

나는 RBENV 코드 기반을 작업 중이었고 발견했습니다.rbenv-init파일 라인 116, 명령문이 포함된 함수를 만듭니다 switch. 내 가정은 변수의 값이 command(복수형) 변수의 값 배열 구성원 중 하나인지 확인하는 것입니다 commands. 그렇다면 스위치 문의 분기 1을 실행합니다. 그렇지 않으면 분기 2를 실행합니다.

나는 내 가설을 테스트하기 위해 간단한 스크립트를 작성하고 싶어서 다음과 같이 썼습니다.

#!/usr/bin/env fish

set command "foo"

switch $command
case ${argv[*]} 
  echo "command in args"
case "*" 
  echo "command not found"
end

그러나 이 스크립트를 실행하면 다음 오류가 발생합니다.

$ ./foo bar baz

./foo (line 6): ${ is not a valid variable in fish.
case ${argv[*]} 
      ^
warning: Error while reading file ./foo

argv나는 스크립트에 제공하는 두 개의 매개변수를 포함하고 평가될 배열을 기대하고 있었습니다 . 내 구문은 소스 코드의 117행 구문과 일치합니다.barbazcase ${commands[*]}

내가 스크립트를 실행하는 쉘은 zsh v5.8.1이지만 내 shebang은 특별히 "fish" 쉘을 참조하므로 쉘이 중요하지 않다고 생각합니다. 나는 fish v3.5.1을 설치했습니다.

답변1

배쉬 코드는 다음과 같습니다:

commands=(`rbenv-commands --sh`)

rbenv-commands --sh이것은 Split+glob이 적용 되고 결과 단어가 요소에 할당된 출력입니다.$commands bash대량으로

case "$shell" in
fish )
  cat <<EOS
function rbenv
  set command \$argv[1]
  set -e argv[1]
  switch "\$command"
  case ${commands[*]}
    rbenv "sh-\$command" \$argv|source
  case '*'
    command rbenv "\$command" \$argv
  end
end
EOS
  ;;

cat << EOS...일부 fish코드가 출력되지만 EOS코드가 참조되지 않으므로 확장은 여전히 ​​(bash를 통해) 실행됩니다. 백슬래시가 앞에 오지 않으면 $param확장됩니다 bash. 대부분 $의 은 접두사로 예상되지만 \그렇지 않습니다 ${commands[*]}(어차피 Fish 구문이 아니라 Korn 셸 구문임). bash는 이를 $commands첫 번째 문자와 $IFS연결된 배열 요소 로 확장합니다(기본값은 공백).

따라서 이 명령으로 생성된 Fish 코드는 cat다음과 같습니다.

function rbenv
  set command $argv[1]
  set -e argv[1]
  switch "$command"
  case elements of the commands bash array
    rbenv "sh-$command" $argv|source
  case '*'
    command rbenv "$command" $argv
  end
end

문자열이 목록에 있는지 확인하려면 fish' containsbuitin을 사용할 수 있습니다.

set list foo bar baz
set string foo
if contains -- $string $list
  echo $string is in the list
end

(예: zsh if (( $list[(Ie)$string] ))또는 비어 있지 않은 목록 if [[ $string = (${(~j[|])list}) ]])

다음과 같이 할 수도 있습니다.

switch $string
  case $list
    echo $string matches at least one of the patterns in the list
end

( 목록의 요소에 *또는 문자가 포함되어 있지 않으면 ?이는 동일하지 않습니다 .)

(이것은 (비어 있지 않은 목록의 경우) zsh' 와 유사합니다 .)[[ $string = (${(j[|])~list}) ]]

게다가:

if string match -q -- $pattern $list > /dev/null
  echo at least one of the elements of the list matches $pattern
end

(예를 들어 zsh) if (( $list[(I)$pattern] )).

관련 정보