나는 사용자에게 도메인 이름을 묻는 쉘 스크립트를 작성 중입니다. 사용자에게 입력 내용을 반복하여 입력하고 유효한 도메인 이름이 아닌 경우 오류 메시지를 작성하라는 메시지를 표시하고 싶습니다.
기본적으로 코드는 다음과 같아야 합니다.
#!/bin/bash
read -p "Enter domain name: " DOMAIN_NAME
while [[ testing for valid domain name goes here ]]
do
echo ''
echo 'You entered an invalid domain name. Please re-enter.'
echo '... more error message data ....'
echo ''
read -p "Enter domain name: " DOMAIN_NAME
done
echo "You entered domain name: $DOMAIN_NAME"
"=~" 연산자를 사용하여 정규식을 테스트하는 방법을 보여주는 몇 가지 예를 찾았습니다. 그러나 이러한 예는 모두 UNTIL
루프를 보여줍니다. 질문에 대한 답변에 정규식을 사용하세요.Bash에서 정규식을 사용하여 유효한 (하위)도메인 확인, 예는 다음과 같습니다
# !/bin/bash
until [[ "$DOMAIN_NAME" =~ ^([a-zA-Z0-9](([a-zA-Z0-9-]){0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,5}$ ]]
do
read -p "Enter domain name: " DOMAIN_NAME
done
echo "You entered domain name: $DOMAIN_NAME"
이 방법은 작동하지만 사용자가 잘못된 데이터를 입력한 경우 추가 오류 메시지를 작성하는 것은 간단하지 않습니다. 이러한 메시지는 루프 내부, 이전에 작성되어야 read
하지만 첫 번째 반복에는 작성되지 않습니다.
이러한 이유로 나는 while
위에 표시된 대로 루프를 작성하는 것이 좋습니다. until
루프를 루프로 다시 작성할 while
때 필요한 테스트 표현식을 부정하는 방법을 찾을 수 없습니다 .
답변1
until cmd
동일합니다 while ! cmd
.
여기서는 다음을 수행하세요.
until
IFS= read -rep 'Enter domain name: ' domain
[[ $domain =~ $regexp ]]
do
printf>&2 'Invalid domain: "%s"\n' "$domain"
done
printf 'You entered: "%s"\n' "$domain"
그것은 다음과 같습니다:
while
IFS= read -rep 'Enter domain name: ' domain
! [[ $domain =~ $regexp ]]
do
printf>&2 'Invalid domain: "%s"\n' "$domain"
done
printf 'You entered: "%s"\n' "$domain"
또는:
while
IFS= read -rep 'Enter domain name: ' domain
[[ ! $domain =~ $regexp ]]
do
printf>&2 'Invalid domain: "%s"\n' "$domain"
done
printf 'You entered: "%s"\n' "$domain"
루프의 조건부 부분에 /가 있으므로 read
정규식 테스트 전에 매번 실행되지만 종료 상태를 확인하지는 않습니다. 루프의 분기를 결정하는 것은 조건부 섹션(여기 또는 )에서 실행되는 마지막 명령입니다.while
until
[[ ... ]]
! [[ ... ]]
또한 로케일을 C로 수정하거나 범위가 코드 포인트를 기반으로 하는 zsh와 같은 셸로 전환하지 않는 한 입력 유효성 검사에 문자 범위를 사용할 수 없다는 점을 명심하세요.
#! /bin/zsh -
set -o extendedglob
until
domain=
vared -p 'Enter domain name: ' domain
[[ $domain = ([a-zA-Z0-9]([a-zA-Z0-9-](#c0,61)[a-zA-Z0-9]|).)##[a-zA-Z](#c2,5) ]]
do
printf>&2 'Invalid domain: "%s"\n' "$domain"
done
printf 'You entered: "%s"\n' "$domain"
(여기서는 vared
(var editor) 내장 기능을 사용하여 bash와 같은 zsh 라인 편집기를 사용합니다 read -e
).
전역 패턴 일치를 위한 with 대신 =~
정규식 일치를 위해 in을 사용하는 경우 이 옵션을 사용하여 PCRE를 사용하고 있는지 확인해야 합니다 . 기본적으로 bash와 같은 ERE를 얻을 수 있지만 모든 제한 사항이 있습니다. 하지만 PCRE는 ERE와 동일하다는 점을 기억 하세요 . 그래서:zsh
=
rematchpcre
$
\z
regexp='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,5}\z'
UTF-8 로케일에서 유효한 문자를 형성하지 않는 일련의 바이트는 PCRE 오류를 유발합니다. zsh glob 모드를 사용하면 이러한 문제를 보다 원활하게 처리할 수 있습니다.
Bash에서 C 로케일 외부에서 이 10개 문자만 일치시키려면(옵션 활성화 여부에 관계없이) [0123456789]
대신 필요합니다. 또는와 같습니다. 적어도 bash에서는 변수에 NUL 바이트가 포함될 수 없으므로 해당 바이트와 일치하지 않는 정규 표현식에 대해 걱정할 필요가 없습니다.[0-9]
globasciiranges
[a-z]
[A-Z]
또한 기억하세요:
- bash에서는
read
없이 사용하거나-r
사용하지 않고 사용하는 것은IFS=
거의 의미가 없습니다 . echo
임의의 데이터를 출력하는 데 사용해서는 안됩니다.- 오류는 stderr로 전송되어야 합니다.