이것은 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
정규 표현식의 일반 규칙(및 더 큰 코드 조각의 버그): 이를 잘라내고 단계별로 다시 빌드하거나 이분법을 사용하십시오. 무엇이든 귀하에게 더 적합합니다.
이 경우 범인은 밑줄로 밝혀졌습니다. 백슬래시를 사용하여 이스케이프 처리하면 제대로 작동합니다.