Bash 함수 매개변수의 이상한 동작

Bash 함수 매개변수의 이상한 동작

다음과 같은 bash 기능이 있습니다.

lscf() {
  while getopts f:d: opt ; do
    case $opt in
      f) file="$OPTARG" ;;
      d) days="$OPTARG" ;;
    esac
  done

  echo file is $file
  echo days is $days
}

매개변수를 사용하여 이 명령을 실행하면 값이 출력되지 않습니다. 인수 없이 함수를 실행한 다음 다시 인수를 사용하여 함수를 실행한 후에만 올바른 값이 출력됩니다.

-bash-4.1$ lscf -d 10 -f file.txt
file is
days is

-bash-4.1$ lscf
file is
days is

-bash-4.1$ lscf -d 10 -f file.txt
file is file.txt
days is 10

내가 뭐 놓친 거 없니?

답변1

귀하의 질문에 나온 함수의 초기 실행을 재현할 수는 없지만 OPTIND함수를 반복적으로 호출할 때 함수의 명령줄을 처리할 수 있도록 함수를 1로 재설정해야 합니다.

bash매뉴얼 에서 :

OPTIND쉘 또는 쉘 스크립트가 호출될 때마다 1로 초기화됩니다. 옵션에 매개변수가 필요한 경우 getopts매개변수를 변수에 넣으세요 OPTARG. 쉘은 OPTIND 자동으로 재설정되지 않습니다. getopts새 매개변수 세트를 사용하려면 동일한 쉘 호출 간에 수동으로 재설정해야 합니다.

~에서POSIX 표준:

애플리케이션의 OPTIND값이 1로 설정된 경우 새 매개변수 세트(현재 위치 매개변수 또는 새 인수 값)를 사용할 수 있습니다.getopts모든 호출에서 서로 다르거나 OPTIND값을 1이 아닌 값으로 수정하는 인수(위치 매개변수 또는 인수 피연산자)를 사용하여 단일 셸 실행 환경 내에서 여러 호출을 시도하면 지정되지 않은 결과가 생성됩니다.

매뉴얼에서는 bashPOSIX 텍스트가 쉘 스크립트 또는 대화형 쉘을 참조하는 "단일 실행 환경"을 참조하는 것과 같은 방식으로 "쉘 호출"을 참조합니다. 스크립트 또는 대화형 셸에서 여러 번 호출하면 lscf동일한 환경에 있게 되며 각 호출 전에 1로 재설정해야 합니다.getoptsOPTIND

그래서:

lscf() {
  OPTIND=1

  while getopts f:d: opt ; do
    case $opt in
      f) file="$OPTARG" ;;
      d) days="$OPTARG" ;;
    esac
  done

  echo file is $file
  echo days is $days
}

변수 filedays해야 하는 경우아니요호출 쉘의 환경에 설정되면 로컬 변수여야 합니다. 또한 참조 변수가 확장되어 printf변수 데이터를 출력하는 데 사용됩니다.

lscf() {
  local file
  local days

  OPTIND=1

  while getopts f:d: opt ; do
    case $opt in
      f) file="$OPTARG" ;;
      d) days="$OPTARG" ;;
    esac
  done

  printf 'file is %s\n' "$file"
  printf 'days is %s\n' "$days"
}

관련 정보