Bash 스크립트의 정규식

Bash 스크립트의 정규식

이것은 bash 스크립팅이 처음이므로 아마도 쉬운 실수를 저지르고 있을 것입니다.

기본적으로 저는 사용자의 그룹을 가져오는 스크립트를 작성하려고 하며, 해당 사용자가 특정 그룹에 속해 있으면 이에 따라 기록합니다. 분명히 더 많은 기능이 있을 것이지만 정규식을 작동시킬 수 없는 경우에는 아무런 의미가 없습니다!

지금까지 나는 이것을 가지고 있습니다 :

#!/bin/bash

regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"

# example output
groups="username : username usergroup"

echo "$groups" >> /home/jrdn/log

if [[ "$groups" =~ $regex ]]; then
    echo "Match!" >> /home/jrdn/log
else
    echo "No match" >> /home/jrdn/log
fi

정규식을 시도한 모든 곳에서 작동합니다. 그러나 bash 스크립트에서는 , 그 $groups뒤에 만 출력됩니다 No match. 그럼 누군가 나에게 무엇이 문제인지 말해 줄 수 있습니까?

답변1

에서 man 7 regex:

대괄호 표현식은 "[]"로 묶인 문자 목록입니다. …

… 리터럴 '-'를 포함하려면 첫 번째 또는 마지막 문자로 만드십시오… [A]'\'를 포함한 다른 특수 문자는 대괄호 표현식 내에서 특별한 의미를 잃습니다.

egrep으로 정규 표현식을 시도하면 오류가 발생합니다.

$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end

다음은 오류가 발생하는 더 간단한 버전입니다.

$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end

특별하지 않기 때문에 \그것은 범위입니다 [a-z]. 다음과 -같이 끝에 넣어야 합니다 [_-].

echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup

이는 libc 버전(egrep 또는 bash)에 관계없이 작동합니다.

편집하다:이는 실제로 로케일 설정에 따라 달라집니다. 맨페이지에서는 이에 대해 경고합니다.

범위는 배열 순서에 크게 의존하므로 이식 가능한 프로그램은 범위에 의존하지 않아야 합니다.

예를 들어:

$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'
\_

물론 오류가 발생하지 않았더라도 원하는 작업을 수행하지 않습니다.

$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'
\^_

\이는 ASCII에서 , [, ^및 를 포함하는 범위입니다 _.

답변2

정규 표현식의 일반 규칙(및 더 큰 코드 조각의 버그): 이를 잘라내고 단계별로 다시 빌드하거나 이분법을 사용하십시오. 무엇이든 귀하에게 더 적합합니다.

이 경우 범인은 밑줄로 밝혀졌습니다. 백슬래시를 사용하여 이스케이프 처리하면 제대로 작동합니다.

관련 정보