정규식과 변수를 사용한 AND 조건

정규식과 변수를 사용한 AND 조건

파일에서 읽은 줄에 변수에 저장된 단어가 포함된 특정 시작과 끝이 있는지 테스트하고 싶습니다. 다음은 몇 가지 코드입니다.

입력 파일은 다음과 같습니다.

line one
#; line two
#; line three blah
line four

실패하는 최소 스크립트는 다음과 같습니다.

declare ENDOFLINE= "blah"
exec 3< "inputfile"

while read LINE <&3
do
    if [[ ("$LINE" =~ "^#;") && (( ("$LINE" =~ "${ENDOFLINE%$}") )) ]]; 
    then
    echo score!
    else echo no score
    fi
done

그러나 이렇게 하면:

if [[ ("$LINE" =~ "^#;") && (( ("$LINE" =~ "blah$") )) ]];

올바른 줄(=> #; 세 번째 줄 등)을 성공적으로 식별했습니다. 즉, 줄의 시작이 "#;"이고 줄의 끝이 $ENDOFLINE 변수에 포함된 문자열인 경우 첫 번째 테스트를 수행하는 복합 테스트 조건이 필요합니다.

도와주셔서 감사합니다.

답변1

단순한 실수처럼 보입니다. ${ENDOFLINE%$}끝에서 a를 제거했지만 원하는 것은 문자 그대로 사용하고 그 뒤에 a를 붙여 줄의 끝을 표시하는 것입니다.$$ENDOFLINE$ENDOFLINE$

if [[ ("$LINE" =~ "^#;") && (( ("$LINE" =~ "${ENDOFLINE}$") )) ]];

이것은 zsh에서는 작동하지만 ksh 또는 bash에서는 작동하지 않습니다. Bash에서는 정규식을 $따옴표로 묶어야 하며(그렇지 않으면 문자 그대로 해석함), ksh는 내부에 이중 괄호가 있는 것을 좋아하지 않습니다 [[ … ]](산술 명령으로 해석함). 이 간단한 코드 줄은 세 가지 셸 모두에서 작동합니다( 변수 확장이 필요하지 않은 몇 안 되는 위치 중 하나 [[…]]입니다 )."…"

if [[ $LINE =~ ^"#;" && $LINE =~ $ENDOFLINE$ ]];

$ENDOFLINE와 겹치지 않는 경우 #;(예: ENDOFLINE이면 ;foo수락 #;;foo하지만 거부함 #;foo) 이를 단일 테스트로 줄일 수 있습니다.

if [[ $LINE =~ ^"#;".*$ENDOFLINE$ ]];

여기서 정규식 대신 와일드카드 패턴을 사용할 수도 있습니다.

if [[ $LINE = "#;"*"$ENDOFLINE" ]];

[[…]]구성은 모든 쉘에 존재하지 않으며 bash, ksh 및 zsh에만 해당됩니다. 다른 쉘(Bourne, dash, POSIX)에서는 와일드카드 일치를 위해 다음 구성을 사용할 수 있습니다 case.

case $LINE in
  "#;"*"$ENDOFLINE") echo score;;
  *) echo no score;;
esac

답변2

grep을 사용하여 이 작업을 수행할 수도 있습니다.

end=blah
while read line; do
    if grep -Eq "^#;.*$end$" <<< "$line"; then
        echo score!
    else
        echo no score
    fi
done

(이것은 bash에 있습니다. 다른 쉘에서는 구문이 약간 다를 수 있지만 원칙은 동일합니다.)

관련 정보