grep의 이스케이프 문자 [

grep의 이스케이프 문자 [

표준 입력에서 문자열을 읽고 있는데 해당 문자열과 일치하는 사용자를 표시하고 싶습니다. 문제는 사용자가 "[" 문자나 이를 포함하는 문자열을 입력하는 경우입니다.

grep -F줄은 문자열(^ - -F를 사용한 단순 문자)로 시작해야 하기 때문에 작동하지 않습니다. 또한 getent $userID가 아닌 사용자 이름만 필요하기 때문에 좋지 않습니다.

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모든 문자 cd. 이제 귀하의 경우에는 이 구문이 특별 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 래퍼 작성을 건너뛰겠습니다.

관련 정보