bash에서 변수에 공백이 아닌 여러 줄이 있는지 여부를 어떻게 테스트합니까? 바꿈 문자를

bash에 두 개의 변수가 있다고 가정 해보십시오.

MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"

변수에 실제로 두 줄 이상의 텍스트가 포함되어 있는지 확인하고 추가 줄 바꿈 문자를 무시합니다.

그래서 이건:

if [ some test on "$MULTILINE" ]; then echo 'yes'; else echo 'no'; fi

인쇄 yes하고 이것을 :

if [ some test on "$SINGLE_LINE" ]; then echo 'yes'; else echo 'no'; fi

인쇄 no합니다.

내 경우에는 빈 줄을 넣는 것에 대해 걱정할 필요가 없지만 그렇게하는 방법을 아는 것은 아프지 않습니다.

어떻게해야합니까?



답변

내가 아는 가장 간단한 해결책은 다음과 같습니다.

if (( $(grep -c . <<<"$MULTILINE") > 1 ))

예 :

VAR="a
b"
if (( $(grep -c . <<<"$VAR") > 1 )); then
  echo VAR has more than one line
else
  echo VAR has at most one line
fi

==>

VAR has more than one line

위의 모든 빈 줄은 무시합니다. 선행, 후행 및 내부. 그러나 공백이 아닌 줄이 두 개 이상 있지 않으면 내부 공백 줄을 가질 수 없으므로 공백 줄이 트리밍 된 후 줄이 두 개 이상 있는지 여부를 변경할 수 없습니다.


답변

$ echo "$ MULTILINE"| 화장실 -l
2

$ echo "$ SINGLE_LINE"| 화장실 -l
2

$ echo "$ SINGLE_LINE"| sed -re '/ ^ $ / d'| 화장실 -l
1

$ echo "$ MULTILINE"| sed -re '/ ^ $ / d'| 화장실 -l
2

sed를 사용하여 공백과 빈 줄을 자르거나 삭제하는 방법에 대한 자세한 내용은 /programming/16414410/delete-empty-lines-using-sed
를 참조 하십시오 .

이제 인용 부호 안에 if expression ...사용 $( ... )하여 행 수를 얻고 숫자에 대해 테스트하십시오.

if [ "$ (echo"$ MULTILINE "| sed -re '/ ^ $ / d'| wc -l)"-gt 1]; 그때
  '두 줄 이상'을 반향하십시오.
그밖에
  '단일 또는 줄 없음'에코;
fi


답변

이 코드 를 약간 수정하면 됩니다. 다음과 같이 재사용을 위해 자체 스크립트에 넣을 수 있습니다.

#!/bin/bash
nlhit=""
for (( i=0; i<${#1}; i++ )); do
    if [[ "${1:$i:1}" == $'\n' ]]; then
        nlhit="1"
    elif [[ "$nlhit" == "1" ]]; then
        exit 1
    fi
done

exit 0

그런 다음 이전 스크립트의 이름을 가정하면 다음과 같이 사용할 수 있습니다 multiline-check.sh.

#!/bin/bash

EMPTYLINE=""
BLANKLINE="    "
ONLYLINES="


"

MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"
SECOND_LINE="
I begin with a newline"


echo -n "EMPTYLINE Check: "
multiline-check.sh "$EMPTYLINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "BLANKLINE Check: "
multiline-check.sh "$BLANKLINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "ONLYLINES Check: "
multiline-check.sh "$ONLYLINES"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "MULTILINE Check: "
multiline-check.sh "$MULTILINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "SINGLE_LINE Check: "
multiline-check.sh "$SINGLE_LINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "SECOND_LINE Check: "
multiline-check.sh "$SECOND_LINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi


답변

후행 빈 줄 무시

다음을 사용하는 접근법이 있습니다 awk.

echo "$TEST" | tac | awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }' && echo "Found A Single Line"

작동 방식 :

  • 에코 “$ TEST”

    이것은 우리가 관심있는 쉘 변수를 취하여 표준 출력으로 보냅니다.

  • tac

    마지막 행이 먼저 리턴되도록 행 순서를 반대로합니다. 를 실행 한 후 tac후행이 선행 행이됩니다.

    (이름 tac은 역순으로 작동 cat하는 이유 와 반대입니다.)taccat

  • awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }'

    이것은 비어 있지 않은 첫 번째 줄의 줄 번호를 변수에 저장 f합니다. 모든 줄을 읽은 후 f총 줄 수와 비교 됩니다 NR. 경우 fIS가 동일 NR, 우리는`다음 코드로 종료, 단 한 줄 (초기 공백을 무시)와 첫 번째 빈 라인 후 하나 개 이상의 라인이 있다면 우리는 코드 0으로 종료했다.

  • && echo "Found A Single Line"

    경우 awk코드 0으로 종료 한 후 echo문이 실행됩니다.

선행 및 후행 빈 줄 모두 무시

하나의 추가 awk변수 를 작성 하여 테스트를 확장하여 선행 및 후행 공백 행을 모두 무시할 수 있습니다.

echo "$TEST" | awk 'first==0 && /./ {first=NR} /./ {last=NR} END{if(first==last){exit 0}; exit 1 }' && echo " Found A Single Line"

이 버전의 awk코드는 선행 및 후행 공백을 모두 처리하므로 tac더 이상 필요하지 않습니다.

awk코드를 한 번에 한 조각 씩 가져 오기 :

  • first==0 && /./ {first=NR}

    변수 first가 0 (또는 아직 설정되지 않은)이고 행에 문자가있는 문자이면 first행 번호 로 설정 하십시오. 때 awk라인을 읽는 완료, first최초의 공백이 아닌 행의 행 번호로 설정됩니다.

  • /./ {last=NR}

    행에 문자가 있으면 변수 last를 현재 행 번호 로 설정하십시오 . awk모든 줄을 읽었을 때 ,이 변수는 마지막 비 공백 줄의 줄 번호를 갖습니다.

  • END{if(first==last){exit 0}; exit 1 }

    이것은 모든 줄을 읽은 후에 실행되었습니다. 경우 firstIS가 동일 last, 우리는 0 개 라인이 아닌 빈 라인과 본 awk코드로 종료 0. 그렇지 않으면 code로 종료됩니다 1. 쉘 스크립트는 보통 if문 또는 &&또는 로 종료 코드를 테스트 할 수 있습니다 ||.


답변