bash 정규식은 모든 그룹을 인식하지 못합니다

bash 정규식은 모든 그룹을 인식하지 못합니다

정규식에서 그룹을 캡처해야 합니다. 하지만 BASH_REMATCH일부 그룹을 가져올 수 없기 때문에 bash 변수의 개념을 이해하지 못하는 것 같습니다 . 이것은 내 코드입니다.

# I want to get the values around the first '=' if it exists
inp="short =  some word  long = span desc=sth to ' be ' described value=45"
regex="\s*(\w*)\s*=\s*(.*)"

if [[ $inp =~ $regex ]]; then 
  echo; 
  echo -e "input: \"$inp\""; 
  echo -e "regex: \"$regex\"";   
  echo "matching groups: ${#BASH_REMATCH[*]}"; 
  for i in $(seq 0 $(( ${#BASH_REMATCH[*]}-1 ))); do 
    echo -e "$i: \"${BASH_REMATCH[$i]}\""; 
  done; 
fi

input: "short =  some word  long = span desc=sth to ' be ' described value=45"
regex: "\s*(\w*)\s*=\s*(.*)"
matching groups: 3
0: "=  some word  long = span desc=sth to ' be ' described value=45"
1: ""
2: "  some word  long = span desc=sth to ' be ' described value=45"

나는 첫 번째 그룹이 "짧을" 것으로 예상했습니다. 왜 인식되지 않나요? regex101.com에서 정규식을 테스트하면 그룹 1이 "짧음"이라고 표시됩니다. 링크는 다음과 같습니다: https://regex101.com/r/oZGQS6/1


편집 1

첫 번째 그룹은 sed를 사용하여 식별됩니다(그룹화 대괄호를 제외하고 동일한 정규식을 사용했습니다).

$ sed 's/\s*\(\w*\)\s*=\s*\(.*\)/\1\n\2/' <<< $inp
short
some word  long = span desc=sth to ' be ' described value=45

편집 2

제안된 대로 앵커를 정규식에 넣으려고 했지만 이번에는 결과가 인식되지 않았습니다.

regex="^\s*(\w*)\s*=\s*(.*)"
regex="^\s*(\w*)\s*=\s*(.*)$"
regex="^\s*(\w+)\s*=\s*(.*)$"

이러한 정규식은 작동하지 않으며 전혀 결과를 얻지 못합니다.

문자열의 16진수 값을 확인했습니다.

$ od -vAn -tx1c <<<"$inp"
           73  68  6f  72  74  20  3d  20  20  73  6f  6d  65  20  77  6f
           s   h   o   r   t       =           s   o   m   e       w   o
           72  64  20  20  6c  6f  6e  67  20  3d  20  73  70  61  6e  20
           r   d           l   o   n   g       =       s   p   a   n    
           64  65  73  63  3d  73  74  68  20  74  6f  20  27  20  62  65
           d   e   s   c   =   s   t   h       t   o       '       b   e
           20  27  20  64  65  73  63  72  69  62  65  64  20  76  61  6c
               '       d   e   s   c   r   i   b   e   d       v   a   l
           75  65  3d  34  35  0a                                        
           u   e   =   4   5  \n 

이상한 캐릭터는 아닌 것 같습니다.

참고로 저는 Mac에서 bash v 4.4.0을 사용하고 있습니다.

$ bash --version
GNU bash, version 4.4.0(1)-release (x86_64-apple-darwin15.6.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

편집 3

뭔가 새로운 것을. bash v.4.1.2를 사용하여 Linux 시스템에서 이 작업을 시도했지만 결과가 좋지 않았습니다.

$ bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

세 가지 정규 표현식이 모두 유효합니다.

regex="\s*(\w*)\s*=\s*(.*)"
regex="^\s*(\w*)\s*=\s*(.*)"
regex="^\s*(\w*)\s*=\s*(.*)$"
regex="^\s*(\w+)\s*=\s*(.*)$"

결과는 다음과 같습니다.

input: "short =  some word  long = span desc=sth to ' be ' described value=45"
regex: "^\s*(\w*)\s*=\s*(.*)"
matching groups: 3
0: "short =  some word  long = span desc=sth to ' be ' described value=45"
1: "short"
2: "some word  long = span desc=sth to ' be ' described value=45"

이것이 바로 제가 기대했던 것입니다. 그런데 왜 내 Mac에서는 작동하지 않나요? Bash 버전이 업데이트되었습니다. 나는 모든 최신 버전의 bash에서 작동하는 솔루션을 원합니다.

답변1

Bash의 정규식은 고정되어 있지 않습니다. 이는 문자열의 어느 위치에서나 일치할 수 있음을 의미합니다. 이는 정규식 엔진에 따라 다릅니다. 여기서 일치는 그림과 같이 등호로 시작됩니다 BASH_REMATCH[0].

^해결 방법: 문자열 시작 부분에 a 를 추가하세요 regex.

[업데이트] 위에서 언급한 것처럼 bash정규식 엔진( man 3 regex)을 사용하세요. 이는 플랫폼마다 다를 수 있습니다. 정규식에 문제가 있는 경우 \letter바로가기를 피하고 Posix에 해당하는 것을 사용하세요.

regex="^\s*(\w*)\s*=\s*(.*)"
예 를 들어,regex="^[[:space:]]*([_[:alnum:]]*)[[:space:]]*=[[:space:]]*(.*)"

관련 정보