이것이 내가 가진 것입니다. 3개의 입력을 검증하려고 합니다. 첫 번째와 두 번째 입력에서는 올바른 입력을 요구하지 않습니다. 뭐가 잘못 되었 니?
#!/bin/bash
while :
do
echo "Please enter your tittle:"
read TITTLE
echo "Please enter your surname:"
read SURNAME
echo "Please enter your ID No."
read ID
if [ "$TITTLE" = "" ] || [ "${TITTLE//[!0-9]}" != "" ];
then
echo "Enter your valid tittle without special characters."
echo "Please try again."
exit 1
fi
if [ "$SURNAME" = "" ] || [ "${SURNAME//[!0-9]}" != "" ];
then
echo "Enter your valid surname without special characters."
echo "Please try again."
exit 1
fi
if [ "$ID" = "" ] || [ "${ID//[0-9]}" != "" ];
then
echo "Enter your valid ID No. without special characters."
echo "Please try again"
else
echo "Thank you" $TITTLE $SURNAME
break
fi
done
답변1
귀하의 스크립트출구직함이나성에 유효하지 않은 입력이 제공되면 루프가 쓸모 없게됩니다. continue
반복을 다시 수행하는 데 사용됩니다 .
그러나 사용자가 잘못된 ID를 입력했다는 이유만으로 직함과 성을 다시 입력하도록 강요하고 싶지는 않으므로 하나의 큰 루프가 아닌 세 개의 입력 루프가 필요합니다. 사용자로부터 읽는 각 항목마다 하나의 루프가 있습니다.
귀하의 코드는 불필요하게 반복적이며 세 개의 루프로 다시 작성됩니다.또한불필요하게 반복적이게 됩니다. 별도의 입력 기능이 있으면 더 편리할 것 같습니다.
다음 스크립트에서는 이를 수행했습니다. 입력 함수는 get_input
"레이블"(사용자가 입력해야 하는 내용에 대한 설명)과 입력의 각 문자가 일치해야 하는 패턴을 사용합니다. 이 get_input
함수는 표준 출력에 유효한 문자열을 출력하므로 스크립트의 주요 부분에 있는 명령 대체 내에서 함수를 호출합니다.
또한 문자열 유효성 검사를 자체 기능으로 옮겼습니다. 이는 함수를 더 깔끔하게 만들고 get_input
유효성 검사 논리를 입력 논리에서 분리하기 위한 것입니다.
유효성 검사에서는 사용하는 것과 동일한 접근 방식을 사용합니다. 즉, 문자열에서 유효한 문자를 모두 삭제한 다음 남은 문자가 있는지 테스트합니다. 이 경우 문자열은 유효성 검사에 실패합니다.
#!/bin/bash
# Succeeds if the first argument is non-empty and only
# consists of characters matching the pattern in the
# second argument.
is_valid () {
local string pattern
string=$1
pattern=$2
[ -n "$string" ] && [ -z "${string//$pattern}" ]
}
# Asks user for input until the given string is valid.
# The first argument is a text string describing what
# the user should enter, and the second argument is a
# pattern that all characters in the inputted data much
# match to be valid.
get_input () {
local label pattern
local string
label=$1
pattern=$2
while true; do
read -r -p "Please enter $label: " string
if is_valid "$string" "$pattern"; then
break
fi
# Complain on the standard error stream.
printf 'Invalid input, try again\n' >&2
done
printf '%s\n' "$string"
}
# Get data from user.
title=$( get_input 'your title' '[[:alpha:] ]' ) # title: only letters and spaces
surname=$( get_input 'your surname' '[[:alpha:] ]' ) # surname: same as title
id=$( get_input 'your ID no.' '[[:digit:]]' ) # ID: only digits
# Print what we got.
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
예를 들어 호칭이나 성에도 점을 허용하려면 패턴을 에서 로 변경 [[:alpha:] ]
하세요 [[:alpha:]. ]
. 또는 훨씬 덜 제한적으로 [![:digit:]]
숫자가 아닌 문자(구두점 등 포함)를 허용하는 데 사용할 수 있습니다.
스크립트를 실행하는 사용자와 동일한 이름을 가진 파일에 출력을 저장하려면 스크립트 자체의 출력을 리디렉션합니다.
$ ./script.sh >"$USER.txt"
그러면 스크립트가 실행되고 출력이 이라는 파일로 리디렉션됩니다 $USER.txt
. 여기서 는 $USER
현재 사용자의 사용자 이름입니다(이 변수 및 $LOGNAME
는 일반적으로 셸 및/또는 시스템에 의해 이미 설정되어 있습니다).
printf
마지막 세 줄을 다음과 같이 변경하여 스크립트 자체 내에서 이 작업을 수행할 수도 있습니다.
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} >"$USER.txt"
또는 스크립트에서 사용자로부터 읽은 "성"을 사용하려는 경우:
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} >"$surname.txt"
에게또한터미널에 인쇄하려면 다음을 사용하세요 tee
.
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} | tee "$surname.txt"
사용자가 제공한 입력을 사용하면 잠재적으로 스크립트 사용자가 현재 디렉터리의 임의 파일을 덮어쓸 수 있습니다(권한이 이를 허용하는 경우).