사용자 입력을 받고 오류가 발생하면 프롬프트를 반복하기 위해 while 루프를 만들었습니다.
while true; do
read -p "Enter hostname : " fqdn
pattern="(^[^\.]*\.[^\.]*\.[^\.]*$)"
if [[ -z "$fqdn" ]]; then #if fqdn input is empty
echo "Error! Hostname cannot be empty"
continue
elif [[ ! "${fqdn}" =~ ${pattern} ]]; then
echo "Error! Format incorrect"
continue
else
echo "hostname is $fqdn"
break
fi
done
내 목표:
- 의 경우만약/엘리프프롬프트를 두 번만 표시한 다음 종료하는 방법을 보여줍니다.
- 위의 while 루프를 개선할 수 있는 방법이 있습니까? 예를 들어 케이스 스위치. 케이스 전환을 이해하기 어렵나요?
운영 체제: Ubuntu 20.04(헤드리스)
답변1
다음 bash
스크립트는 사용자로부터 문자열을 읽고 해당 문자열이 적용하려는 호스트 이름의 조건을 충족하는지 테스트합니다.
명령문에 사용된 두 패턴 중 첫 번째는 case
사이에 문자가 없는 두 점의 병리학적 사례를 테스트합니다(이 패턴은 우리가 조치를 취하지 않는 패턴입니다). 두 번째 패턴에 점이 두 개 이상 있고 양쪽 끝에 점이 없는 문자열이 포함되어 있는지 테스트합니다. fdqn
두 번째 패턴이 문자열과 일치하는 경우에만 호스트 이름 변수가 해당 문자열로 설정됩니다. 이 문자열은 foo..bar
두 번째 패턴과 일치하므로 이중 점 하위 문자열을 첫 번째 패턴과 선제적으로 일치시킵니다.
#!/bin/bash
unset -v count fdqn
while true; do
read -p 'Enter hostname: ' -r
case $REPLY in (*..*) ;; ([!.]*.*.*[!.]) fdqn=$REPLY; break; esac
echo 'Invalid format' >&2
count=$(( count + 1 ))
[ "$count" -eq 2 ] && break
done
if [ -z "$fdqn" ]; then
echo 'No valid hostname entered' >&2
exit 1
fi
printf 'The hostname is "%s"\n' "$fdqn"
이 count
변수는 사용자가 문자열 입력을 시도하는 횟수를 추적합니다. 이 변수의 값이 2에 도달하면 루프를 종료합니다.
case
이식 가능한 스크립트로 만들고 싶지 않은 한 (이 경우 문을 다르게 실행 sh
해야 함 ) 여기서 문을 실제로 사용할 필요는 없습니다 . read
globbing 연산자를 사용할 ==
때 명령문 bash
은 case
다음과 같습니다.
if [[ $REPLY == *..* ]]; then
:
elif [[ $REPLY == [!.]*.*.*[!.] ]]; then
fdqn=$REPLY
break
fi
&&
이 두 테스트는 첫 번째 테스트가 음성인 경우 연결하는 데에도 사용할 수 있습니다.
if [[ $REPLY != *..* ]] && [[ $REPLY == [!.]*.*.*[!.] ]]; then
fdqn=$REPLY
break
fi
세 개의 점이 포함된 호스트 이름을 얻지 않으려면 일치 하지 않아야 하는 것처럼 $REPLY
일치하지 않는지 확인하십시오 .*.*.*.*
*..*
답변2
저는 개선될 수 있다고 생각하는 대안을 생각했습니다.
# declare the pattern outside the loop
pattern="(^[^.]*\.[^.]*\.[^.]*$)"
# declare a counter for failed attempts
c=0
while true; do
# if counter is equal to 2 exit
[[ $c -eq 2 ]] && echo "Two failed attempts. Exiting" && exit
read -p "Enter hostname : " fqdn
if [[ -z "$fqdn" ]]; then
echo "Error! Hostname cannot be empty"
((c++)) # increment the counter
continue
elif [[ ! "${fqdn}" =~ ${pattern} ]]; then
echo "Error! Format incorrect"
((c++)) # increment the counter
continue
fi
# this lines will be executed only if the conditions passed
echo "hostname is $fqdn"
break
done
이 case
구조는 정규식을 사용하지 않으므로 복잡한 일치의 경우 명령문을 사용하는 것이 더 좋습니다 if elif..
.