bash의 if 문 내에서 문자열을 정규식과 일치시키려고 합니다. 코드는 아래와 같이 표시됩니다.
var='big'
If [[ $var =~ ^b\S+[a-z]$ ]]; then
echo $var
else
echo 'none'
fi
일치 항목은 "b"로 시작하고 그 뒤에 공백이 아닌 문자가 하나 이상 오고 az 문자로 끝나는 문자열이어야 합니다. 문자열의 시작과 끝을 일치시킬 수 있지만 \S는 공백이 아닌 문자와 일치할 수 없습니다. 도움을 주셔서 미리 감사드립니다.
답변1
GNU가 아닌 시스템에서 다음은 \S
실패를 설명합니다.
이는 \S
PCRE(Perl Compatible Regular Expressions)의 일부입니다. 그것은 속하지 않는다BRE(기본 정규식)또는ERE(확장 정규식)껍질에 사용됩니다.
=~
이중 괄호 테스트의 Bash 연산자는 [[
ERE를 사용합니다.
일반 문자와 달리 ERE에서 특별한 의미를 갖는 유일한 문자는 입니다 .[\()*+?{|^$
. S
그다지 특별 하지 않습니다 . 보다 기본적인 요소로 정규식을 작성해야 합니다.
regex='^b[^[:space:]]+[a-z]$'
어디대괄호 표현[^[:space:]]
동등하다\S
PCRE 표현:
이제 기본 \s
문자는 HT(9), LF(10), VT(11), FF(12), CR(13) 및 공백(32)입니다.
테스트는 다음과 같습니다:
var='big' regex='^b[^[:space:]]+[a-z]$'
[[ $var =~ $regex ]] && echo "$var" || echo 'none'
그러나 위의 코드는 bißß
예를 들어 일치합니다. 범위에 선택한 로케일(UNICODE) [a-z]
이 아닌 다른 문자가 포함되기 때문입니다. abcdefghijklmnopqrstuvwxyz
이러한 문제를 피하려면 다음을 사용하십시오.
var='bißß' regex='^b[^[:space:]]+[a-z]$'
( LC_ALL=C;
[[ $var =~ $regex ]]; echo "$var" || echo 'none'
)
코드는 목록의 문자( abcdefghijklmnopqrstuvwxyz
마지막 문자 위치)만 일치하지만 중간에 있는 다른 많은 문자(예: )와도 일치합니다 bég
.
그러나 이 사용법은 LC_ALL=C
다른 정규식 범위에 영향을 미칩니다. [[:space:]]
C 로케일에서는 공백만 일치합니다.
모든 문제를 해결하려면 각 정규식을 분리해야 합니다.
reg1=[[:space:]] reg2='^b.*[a-z]$' out=none
if [[ $var =~ $reg1 ]] ; then out=none
elif ( LC_ALL=C; [[ $var =~ $reg2 ]] ); then out="$var"
fi
printf '%6.8s\t|' "$out"
내용은 다음과 같습니다.
- input(var)에 공백이 없으면 (현재 로케일에서)
- a로 시작하고 (C 로캘에서)로 끝나는지 확인하세요
b
.a-z
두 테스트 모두 양수 범위("비" 범위 아님)에서 수행됩니다. 그 이유는 몇 개의 문자를 부정하면 더 많은 일치 항목이 생성되기 때문입니다. UNICODE v8에는 120,737자가 할당되어 있습니다. 범위가 17자를 부정하는 경우 120720개의 다른 가능한 문자를 허용하며 여기에는 인쇄할 수 없는 제어 문자가 많이 포함될 수 있습니다.
중간 문자가 가질 수 있는 문자 범위를 제한하는 것이 좋습니다(예, 해당 문자는 공백이 아니지만 다른 문자일 수 있습니다).
답변2
[[ $var =~ ^b[^[:space:]]+[abcdefghijklmnopqrstuvwxyz]$ ]]
일치하는 항목은 [a-z]
일반적으로 로케일에 따라 다릅니다.아니요(유일한) 그 중 하나입니다 abcdefghijklmnopqrstuvwxyz
.
perl
( 가로 및 세로 공백)은 이제 POSIX 및 bash ERE의 \S
다른 정규식 엔진에서도 인식됩니다 .[^[:space:]]
bash
이러한 정규식을 일치시키려면 시스템의 정규식 라이브러리를 사용하십시오. 하지만 \S
정규식에 연산자가 있는 시스템(예: 최근 GNU 시스템)에서도 다음과 같은 이유로 작동하지 않습니다.
[[ x = \S ]]
bash
호출 regcomp("S")
:
[[ x = '\S' ]]
bash
호출 regcomp("\\S")
(백슬래시 2개)
그러나 bash-3.1을 사용하거나 다음을 사용하여 bash-3.1 호환성을 활성화하는 경우 shopt -s compat31
:
[[ x = '\S' ]]
ERE 지원 시스템에서 작동합니다(공백이 아닌 문자와 일치) \S
.
$ bash -c "[[ x =~ '\S' ]]" || echo no
no
$ bash -O compat31 -c "[[ x =~ '\S' ]]" && echo yes
yes
또 다른 옵션은 정규식을 변수에 넣는 것입니다.
$ a='\S' bash -c '[[ x =~ $a ]]' && echo yes
yes
\S
다시 말하지만, 이는 정규식을 지원하는 Perl과 같은 시스템에서만 작동합니다.
이 특정 코드에 해당하는 POSIX는 다음과 같습니다 bash
.
if expr " $var" : \
' b[^[:space:]]\{1,\}[abcdefghijklmnopqrstuvwxyz]$' \
> /dev/null; then
printf '%s\n' "$var"
else
echo none
fi
또는:
case $var in
([!b]* | *[!abcdefghijklmnopqrstuvwxyz] | *[[:space:]]* | "" | ? | ??)
echo none;;
(*) printf '%s\n' "$var"
esac
답변3
일반화하다
# match any non-whitespace char--works in bash and `grep` too
[^\r\n\t\f\v ]
세부 사항
일치(공백이 아닌 문자)는 분명히 정규 표현식이나 유사한 정규식에서 작동하지 않습니다 \S
. 따라서 공백이 아닌 문자가 하나 이상 나타나는 경우 이를 사용하지 마십시오.bash
grep
# INSTEAD OF THESE (which do NOT work in bash or `grep`)
# match one or more non-whitespace chars
\S+
# or (same thing)
[\S]+
...이것을 사용하세요:
bash
공백이 아닌 문자를 모두 일치시키는 방법 및grep
# match one or more non-whitespace chars (DOES work in bash and `grep`!)
[^\r\n\t\f\v ]+
나는 이것을 배웠다https://regex101.com/. 여기를 클릭하세요:https://regex101.com/r/kM041K/1, 화면 오른쪽의 '도움말' 섹션 아래에 다음이 표시됩니다.
\S
공백이 아닌 문자와 일치합니다( 와 동일[^\r\n\t\f\v ]
).
따라서 정규 표현식에 대해 의문이 있는 경우 이 웹사이트를 방문하여 해당 내용을 확인하십시오.