$REPLY를 arg 함수로 설정하면 작동하지 않습니다.

$REPLY를 arg 함수로 설정하면 작동하지 않습니다.

나는 코드 전체에서 재사용할 검증 while 루프를 위한 fn을 만들기로 결정했습니다.

loopFN() {
   while true; do
      if [ "$1" == "null" ] || ([ "$2" == "phone number" ] && ! [[ "$1" =~ $phone_regex ]]); then
         printf 'enter a valid %s\n' "$2"
         read
         $1=$REPLY
      else
         break
      fi  
   done
}

나는 그것을 이렇게 부른다:

   local number="null"
   loopFN "$number" "phone number"

내 전화번호 정규식은 다음과 같습니다.

phone_regex="^[0-9]{3}-[0-9]{3}-[0-9]{4}"

내가 얻는 오류는 다음과 같습니다.

./newmenu.sh: line 27: null=dasd: command not found

여기서 "dasd"는 메시지가 표시될 때 입력한 것입니다.

while 루프를 재사용하는 것은 나쁜 습관입니까? 몇 번이나 다시 작성해야 하나요? 아니면 내 문법에 문제가 있는 걸까요?

문제는 여기에 있는 것 같습니다(오류에 인용된 27번째 줄).

     $1=$REPLY

fn에 전달된 변수(이 경우 $number)를 설정하려고 합니다. 처음에는 var가 로컬이므로 작동하지 않을 것이라고 생각했지만 로컬 키워드를 제거했는데 오류가 지속됩니다.

편집하다:

제안에 따라 몇 가지 변경 사항을 추가했습니다.

loopFN() {
   while true; do
      if [[ $1 = null ]]; then
         printf>&2 'enter a valid %s\n' "$2"
         IFS= read -r "$1"
      elif [[ $1 = null || ( $2 = 'phone number' && ! $1 =~ $phone_regex ) ]]; then
         printf>&2 "enter a valid phone number\n"
         IFS= read -r "$1"
      else
         break
      fi  
   done
}

답변1

$1=$REPLY=( )의 왼쪽은 $1유효한 변수 이름이 아니므로 변수 할당으로 이해되지 않으므로 명령 인수 또는 명령 인수 목록으로만 처리됩니다( $1$REPLY따옴표가 없기 때문에 분할+glob 적용됨). 명령으로 처리됩니다.

다음을 수행해야 합니다.

eval "$1=\$REPLY"

셸에 contents_of_$1=$REPLY셸 코드로 평가하도록 요청하고 의 내용이 유효한 변수 이름이라고 가정하면 의 값이 해당 변수에 $1할당됩니다 ( 그렇다면 분명히 다시 시작됩니다 ).$REPLY$1reboot;foo

여기에서 다음을 수행할 수도 있습니다.

IFS= read -r "$1"

인수로 사용되는 것을 사용하여 호출 되며 read변수 이름이 문자 그대로 전달되는지 아니면 확장의 결과인지 상관하지 않으며 알 방법도 없습니다.$1read

이는 여전히 명령 주입 취약점입니다(예: when $1is foo[`reboot`]).

어쨌든, 한 줄을 읽는 구문은 IFS= read -r line, 그렇지 않나요 read line?

또한 Korn 스타일 구성 (...)외부에서 하위 쉘을 시작하려면[[...]]

if [ "$1" == "null" ] || ([ "$2" == "phone number" ] && ! [[ "$1" =~ $phone_regex ]])

그 이상이어야 합니다:

if [[ $1 = null || ( $2 = 'phone number' && ! $1 =~ $phone_regex ) ]]

$1변수 이름이라면 의미 $1 =~ $phone_regex가 없을 것입니다. 전화번호는 유효한 변수 이름이 아닌 경우가 많습니다.

라는 변수의 내용을 검사하려는 경우 bash 구문을 사용하여 변수를 역참조하거나 ChatGPT에서 권장하는 대로 최신 버전의 bash에서 ksh93 스타일 이름 인용을 사용할 $1수 있습니다 .${!1}

어떤 경우든 number함수에 전달해야 하는 것은 값( )이 아니라 변수 이름( )입니다.$number

사용자 프롬프트와 상호 작용은 일반적으로 stderr로 이동하고, stdout은 명령으로 생성된 실제 출력과 재사용/사후 처리를 원하는 기타 항목을 위해 예약되어 있습니다.

printf>&2 'enter a valid %s\n' "$2"

특히 bash셸의 경우 내장 옵션을 사용하여 rompt를 실행할 수 있습니다 -p( readstderr p에도 전송됨).

IFS= read -rp "Enter a valid $2: " "$1"

대부분의 다른 Korn 유사 쉘에서 구문은 다음과 같습니다.

IFS= read -r "$1?Enter a valid $2: "

함수가 전화번호를 입력하도록 의도된 경우 사용자가 유효한 전화번호를 입력할 때까지 반복적으로 요청하고 첫 번째 인수에 제공된 이름을 사용하여 변수에 반환한 다음 bash 특정 구문을 사용하면 다음과 같습니다.

input_phone_number() {
  local -n _var_name="$1"
  local _regex='^[0123456789]{3}-[0123456789]{3}-[0123456789]{4,}$'
  until
    IFS= read -rp 'Please enter a valid phone number: ' _var_name ||
      return # return failure upon EOF
    [[ $_var_name =~ $_regex ]]
  do
    echo>&2 'Not a valid phone number, try again.'
  done
}

input_phone_number number || exit

( as [0123456789]대신 사용하여 무엇이든 일치시키고 끝과 시작 부분에 정규식을 고정하십시오).[0-9][0-9]

input입력 유형과 유효성 검사 정규 표현식을 인수로 사용하는 일반 함수 의 경우 :

input() {
  local -n _var_name="$1"
  local _type="$2" _regex="$3"
  until
    IFS= read -rp "Please enter a valid $_type: " _var_name ||
      return # return failure upon EOF
    [[ $_var_name =~ $_regex ]]
  do
    echo>&2 "Not a valid $_type, try again."
  done
}

input number \
      'phone number' \
      '^[0123456789]{3}-[0123456789]{3}-[0123456789]{4,}$' || exit

예를 들어 로컬 변수 가 반환하려는 사용자 변수와 충돌 하지 않도록 _사용자가 작업을 수행할 수 있도록 로컬 변수의 접두사 에 주의하세요 .input type type '^(good|bad)$'$type$type

관련 정보