>

이 형식의 복잡한 문자열이 있습니다 :

inp="key1 =   what' ever the value key2 = the value Nb.2   key3= \"last value\""

첫 번째 값과 관련된 첫 번째 키를 가져와야합니다. bash 정규식을 사용하여 키, 값 및 문자열에서 남은 것을 추출하고 싶습니다.

rkeyval="[[:space:]]*([_[:alnum:]]*?)[[:space:]]*=[[:space:]]*((.*?)[[:space:]]+([_[:alnum:]]+?[[:space:]]*=[[:space:]]*.*))"
if [[ $inp =~ $rkeyval ]]; then
  key=${BASH_REMATCH[1]}
  val=${BASH_REMATCH[3]}
  left=${BASH_REMATCH[4]}
  for i in $(seq 0 $(( ${#BASH_REMATCH[*]}-1 ))); do  
    echo -e "$i: \"${BASH_REMATCH[$i]}\""; 
  done; 
else
  echo "no match"
fi

이 작동하지 않습니다. Bash 4.4가 설치된 Mac에서는 일치하는 항목이 없습니다 :

no match

Red Hat Linux에서 다음과 같은 결과가 나옵니다 :

0: "key1 =   what' ever the value key2 = the value Nb.2   key3= "last value""
1: "key1"
2: "what' ever the value key2 = the value Nb.2   key3= "last value""
3: "what' ever the value key2 = the value Nb.2  "
4: "key3= "last value""

다음과 같은 결과를 기대합니다 :

0: "key1 =   what' ever the value key2 = the value Nb.2   key3= "last value""
1: "key1"
2: "what' ever the value key2 = the value Nb.2   key3= "last value""
3: "what' ever the value"
4: "key3= "last value""

즉, 키는 두 번째 일치 그룹이되고 값은 세 번째 그룹이됩니다.

이 표현은 온라인 PHP 정규식 테스터 에서 작동합니다.

업데이트 된 버전의 Bash가있는 모든 유닉스 머신에서이 기능을 사용하고 싶습니다.

정규식이 Posix 규칙을 존중하더라도 (또는 그렇게합니까) 왜 이것이 작동하지 않는지, 왜 플랫폼마다 결과가 다른지 모르겠습니다. 내가 여기서 뭘 잘못하고 있니?

  • 답변 # 1

    별표는 이미 선택 카운트입니다 (0 문자 일 수 있음). ? 를 추가 할 필요가 없습니다  그것에.

    각 괄호가 키나 값을 캡처해도 괜찮습니까? :

    s='[[:space:]]*'        # spaces
    n='[_[:alnum:]]+'       # a valid name (limited by spaces)
    e="${s}=${s}"           # an equal sign (=).
    rkeyval="${s}(${n})${e}([^=]*) (${n})${e}([^=]*) (${n})${e}(.*)"
    #            1^^^^^    2^^^^^^ 3^^^^^    4^^^^^^ 5^^^^^    6^^^
    echo "$rkeyval"
    
    

    이것은 다음과 같이 캡처됩니다 :

    if [[ $inp =~ $rkeyval ]]; then
        i=0
        while ((i<${#BASH_REMATCH[@]})); do
            printf '%s: "%s"\n' "$((i))" "${BASH_REMATCH[i++]}";
        done
    else
        echo "no match"
    fi
    
    

    인쇄 :

    0: "key1 =   what' ever the value key2 = the value Nb.2   key3= "last value""
    1: "key1"
    2: "what' ever the value"
    3: "key2"
    4: "the value Nb.2  "
    5: "key3"
    6: ""last value""
    
    

    그리고 원하는 값 (코드를 올바르게 이해하면)을 대략적으로 계산할 수 있습니다 (완벽하게 일치하도록 편집하십시오) :

    key="${BASH_REMATCH[1]}"
    val="${BASH_REMATCH[@]:2:3}"
    left="${BASH_REMATCH[@]:5:2}"
    
    

  • 답변 # 2

    POSIX는 *? 를 정의하지 않습니다  Bash가 사용하는 ERE의 경우 대신 다음을 지정하십시오.

    와이즈 비즈

    Bash는 시스템

    The behavior of multiple adjacent duplication symbols ( '+', '*', '?', and intervals) produces undefined results.

    를 사용합니다 / regcomp  정규식 일치를 위해. 애플의 libc는 아마도 regexec 에 대해 원하는 행동을 구현하지 않을 것입니다 .

    그리 디에서 욕심없는 매칭 시맨틱을 복구하는 표준 방법은 없지만,이 경우에는 그중 일부는 불필요하다 (첫 번째 *? ) 예를 들어). 그렇지 않으면 표현식을 다른 것으로 일치 시키거나데이터를 미리 (그리고 나중에) 변경하여 효과를 가져와야합니다.

    [_[:alnum:]]*?

관련 자료

  • 이전 linux mint - 펄스 오디오가 아닌 alsa에 의존하는 그놈 쉘 믹서 아이콘이 있습니까?
  • 다음 autocomplete - 특정 쉘 명령 또는 별명에 대해 완료를 완전히 비활성화하는 방법은 무엇입니까?