
stdin에서 문자열을 읽고 문자열과 일치하는 사용자를 표시하고 싶습니다. 문제는 사용자가 문자 '[' 또는 이를 포함하는 문자열을 입력하는 경우입니다.
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
is 가 이 구문에서 특별하기 [
때문에 [
(글로빙을 수행함) 백슬래시를 접두사로 붙여 이스케이프해야 합니다(예: ) \[
.
이제 교체 부품을 살펴보겠습니다. 필요한 것은 \[
거기에 있습니다. 하지만 다시 말하지만, 이 매개변수 대체 구문에서는 \
및 둘 다 [
특별하므로 ${var//...}
둘 다 그래야 합니다. 예, 짐작하셨겠지만 백슬래시를 사용하면 다음과 같은 표현식이 됩니다 \\\[
. "${var//\[/\\\[}"
HTH
답변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를 인수로 사용합니다( 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 래퍼 작성을 건너뛰겠습니다.