Bash 정규식 및 IFS 분할

Bash 정규식 및 IFS 분할

다음과 같은 문제가 있습니다. 문자열에서 대괄호(대괄호 포함 또는 제외) 안의 텍스트를 추출하고 싶습니다. 내 문자열은 다음과 같습니다

STR="[1] [2][345] [678 9] foo bar"

나는 원래 bash 정규 표현식과 BASH_REMATCH를 사용하고 싶었습니다. 결국 다음 코드를 사용했습니다.

regex='\[([^\]]*)\](.*)'
MATCHES=()
STR="[1] [2][345] [678 9] foo bar"
while [[ -n $STR && $STR =~ $regex ]];
do
    MATCHES+=("${BASH_REMATCH[1]}")
    STR=${BASH_REMATCH[2]}
    echo -e "matches: ${BASH_REMATCH[1]} -> ${BASH_REMATCH[2]}"
done

[345]이 방법은 효과 가 있지만 문제는 대괄호 안의 문자 하나만 캡처하여 3.

왜 이런 일이 일어나는지 이해가 되지 않아서 결국 grep과 PCRE를 사용하게 되었습니다. 내 현재 솔루션은

regex="\[[^\]]*?\]"
if [[ $(grep -o '\[.*\]' <<< $STR) ]];
then
    MATCHES=$(grep -oP "$regex" <<< $STR)
else
    echo "No special flags provided."
    exit 0
fi

그런 다음 for 루프를 진행합니다.

for arg in $MATCHES;
do
    echo $arg
done

문제는 내가 원하는 대로 필드를 분리하지 않는다는 것입니다. 올바른 구분 기호를 찾기 위해 hexdump를 사용했습니다.

hexdump -C <<< $MATCHES

놀랍게도 구분 기호가 0a16진수에서 LF인 것으로 나타났습니다. for 루프가 분할을 위해 IFS를 사용한다는 것을 알고 있기 때문에 이것은 문제가 되지 않습니다. 그런 다음 IFS=$'\n'. (다시 한번) 놀랍게도 0a0ahexdump에 따르면 IFS의 값은 다시 . 그래서 그것은 작동하지 않습니다. 그런 다음 IFS의 값을 로 설정하고 IFS=''(이것이 세 번째로 놀랐습니다) 값을 로 설정했습니다 0a. 하지만 그것도 작동하지 않습니다. for 루프는 동작을 변경하지 않습니다. 어쩌면 내 스크립트가 IFS의 범위를 올바르게 설정하지 않는 것일까요?

내 질문은 다음과 같습니다.

1) 원래 bash 전용 정규식 방법이 작동하지 않는 이유는 무엇입니까? 왜 한 문자만 캡처합니까? regex101 dot com은 예상되는 동작을 보여 주지만 다시 bash 정규식 패턴을 제공하지 않습니다.

2) IFS 세트가 예상대로 작동하지 않는 이유는 무엇입니까? 공백으로 설정하더라도 "추가" LF를 추가합니다.

3) IFS가 for 루프에 영향을 주지 않는 이유는 무엇입니까?

4) 원래 문제를 해결하는 더 쉬운 방법이 있습니까( 각 대괄호 쌍을 반복할 수 있는 방식으로 [foo] [bar] [foo bar]이와 같은 문자열에서 추출 ).[foo] [bar] 1 asdf[foo bar]


보너스 질문!

B) 변수나 표현식을 따옴표나 큰따옴표로 묶어야 할 때 혼란스럽습니다. 와일드카드와 매개변수 확장에 대해 조금 읽었으며 이제 좀 더 심층적인 내용을 찾고 있습니다. 어떤 제안이 있으십니까?

답변1

를 포함하지 않는 비어 있지 않은 문자열을 일치시키려면 ]를 사용하십시오 [^]]+.

[^\]]*will match non \다음에 0 이상이 오는 것을 사용하면 됩니다 ]. 이것이 바로 1및 다른 문자열은 구문 분석하지 못한 이유입니다 2.

IFS변수는 첫 번째 코드에서는 역할을 하지 않습니다. 내부 변수에는 [[ ... ]]큰따옴표가 필요하지 않습니다.

배열의 개별 요소를 인쇄하려면 다음을 사용하십시오.

printf '%s\n' "${MATCHES[@]}"

또는

for elem in "${MATCHES[@]}"; do
    printf '%s\n' "$elem"
done

단지 $MATCHES배열의 첫 번째 요소로 확장됩니다(그리고 값에 토큰화 및 파일 이름 글로빙을 적용합니다).

관련 정보