표준 입력에서 문자열을 읽고 있는데 해당 문자열과 일치하는 사용자를 표시하고 싶습니다. 문제는 사용자가 "[" 문자나 이를 포함하는 문자열을 입력하는 경우입니다.
grep -F
줄은 문자열(^ - -F를 사용한 단순 문자)로 시작해야 하기 때문에 작동하지 않습니다. 또한 getent $user
ID가 아닌 사용자 이름만 필요하기 때문에 좋지 않습니다.
if [[ "$user" == *"["* ]]; then
echo -e "Invalid username.\n"
continue
fi
if ! getent passwd | grep "^$user:"; then
echo -e "Invalid username.\n"
continue
fi
이것은 "["에 대한 해결 방법입니다. 다른 방법이 있습니까?
awk
해당 작업을 수행할 가능성이 가장 높지만 아직 이에 대해 잘 모르고 grep에 관심이 있습니다.
답변1
이스케이프하거나 다음과 같이 문자 클래스에 넣으십시오.
grep '\['
grep '[[]'
grep -e "${user//\[/\\\[}"
${var//c/d}
쉘 변수의 구문 => $var
모든 문자 c
를 d
. 이제 귀하의 경우에는 이 구문이 특별 c
하므로 (글로빙을 수행함) 앞에 백슬래시를 붙여 이스케이프해야 합니다. 즉, .[
[
\[
이제 교체 부품과 관련하여 우리에게 필요한 것은 \[
다음 중 하나입니다. 그러나 매개변수 대체 구문에서는 \
및 둘 다 특별합니다. 예, 짐작하셨겠지만 둘 다 백슬래시가 필요하므로 다음과 같은 표현식이 생성됩니다. [
${var//...}
\\\[
"${var//\[/\\\[}"
화타이
답변2
[
정규식에서 이스케이프해야 하는 유일한 문자는 아닙니다. 모든 RE 연산자에는 .
사용자 이름에서 일반적으로 발견되는 연산자( r.ot
예: 정규식 일치 root
)가 포함됩니다.
또한 귀하의 메소드( getent passwd | grep "^$user:"
)도 유효하지 않은 것으로 표시되지 않았으므로 유효하지 않습니다 root:0
.
여기서는 다음을 사용하는 것이 더 좋습니다 awk
.
user_valid() {
getent passwd |
U="$1" awk -F: '$1 == ENVIRON["U"] {found = 1; exit}
END {exit(1 - found)}'
}
이제 모든 사용자 데이터베이스가 그러한 열거를 허용하는 것은 아닙니다.
$ getent passwd | grep stephane
$ id -u stephane
10631
$ getent passwd stephane
stephane:*:10631:10631:Stephane Chazelas:/export/./home/stephane:/bin/zsh
제 경우에는 사용자가 LDAP 데이터베이스에 있습니다.낱낱이 세다비활성화되어 있지만(수천 명의 사용자가 있을 수 있음), 사용자를 개별적으로 쿼리/구문 분석할 수 있습니다.
따라서 여기서 사용자를 인증하려면 해당 사용자에 대한 사용자 데이터베이스를 직접 쿼리하는 것이 좋습니다. 예를 들어, 다음 id
명령을 사용합니다(표준 명령과 반대 getent
).
user_valid() {
case $1 in
(*[!0-9]*) id -u -- "$1" > /dev/null 2>&1;;
(*) false;;
esac
}
id
( 이 경우 일부 구현에서는 사용자 ID를 제공하기 때문에 모든 숫자 사용자를 별도로 처리합니다 . 대부분의 시스템에서 사용자 이름은 숫자가 될 수 없습니다(이로 인해 사용자 이름 또는 사용자 이름 명령이 필요한 대부분의 시스템이 중단됩니다) id
. 위에, ps
... find
))).
답변3
특수 문자를 이스케이프하는 것은 약간 번거롭습니다. 대신, 먼저 출력에서 사용자 이름 필드를 선택한 getent
다음 나머지 전체 줄과 일치시킬 수 있습니다.
LC_ALL=C
if ! [[ $user =~ ^[A-Za-z0-9._][A-Za-z._-]*$ ]] ; then
echo "Username is invalid"
continue
fi
getent passwd | cut -d: -f1 | grep -xF -e "$user"
-F
고정 문자열의 경우 -x
전체 줄 일치를 위한 것입니다.
사용자 이름이 숫자로만 구성된 사용자가 없는 경우 다음을 사용할 수 있습니다 getent
.
LC_ALL=C
if ! [[ $user =~ ^[A-Za-z0-9._][A-Za-z._-]*$ ]] ; then
echo "Username is invalid"
continue
elif [[ $user =~ ^[0-9]+$ ]] ; then
echo "Cannot handle username of digits only, sorry :("
continue
fi
if ! getent -- passwd "$user" > /dev/null ; then
echo "$user doesn't exist"
continue
fi
getent
또는 숫자 문자열이 사용자 이름이 아니라 UID여야 한다고 가정하는 문제나 다른 사람들을 피하기 위해 다음을 호출해야 합니다.getpwnam()
수동으로. 이는 기본 구현이 수행하는 getpwnam()
것 외에는 사용자 이름에 대해 어떠한 가정도 하지 않습니다 .
export user
if ! perl -e 'exit !defined getpwnam($ENV{user})' ; then
echo "$user doesn't exist"
fi
해당 C 래퍼 작성을 건너뛰겠습니다.