파일에서 읽은 줄에 변수에 저장된 단어가 포함된 특정 시작과 끝이 있는지 테스트하고 싶습니다. 다음은 몇 가지 코드입니다.
입력 파일은 다음과 같습니다.
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에 있습니다. 다른 쉘에서는 구문이 약간 다를 수 있지만 원칙은 동일합니다.)