POSIX 쉘에서 문자열 계산 변수를 사용하는 방법은 무엇입니까?

POSIX 쉘에서 문자열 계산 변수를 사용하는 방법은 무엇입니까?

우분투 컨테이너 내에서 실행되는 스크립트가 있습니다.

#!/bin/sh

name=$(cat < /etc/os-release | grep "^NAME" | cut -d "=" -f 2)

if [ $name = "Ubuntu" ] 
then 
  echo "This should return"
else  
  echo "This is wrong"
fi

다음을 실행하여 컨테이너를 시작합니다.

docker run -it -v $(pwd):/scripts ubuntu:latest /bin/sh /scripts/test.sh

내가 받은 출력은 "This iswrong"입니다. 이는 잘못된 것입니다. 내 노트북이 Ubuntu이므로 $name의 출력이 "Ubuntu"라는 것을 알고 있지만 이런 일이 발생하는 이유를 찾을 수 없습니다. 스크립트에 경로가 있는 이유는 무엇입니까? 컨테이너 외부의 노트북에서도 동일한 작업을 수행합니다.

답변1

이 파일에는 /etc/os-release쉘 호환 변수 할당 목록이 포함되어 있습니다. 쉘 스크립트에서 구문 분석할 필요가 없으며 관련 변수를 사용하기 source만 하면 됩니다..

$ cat ex.sh
#!/bin/sh
. /etc/os-release
echo "$NAME"

$ ./ex.sh
Ubuntu

답변2

데비안에서 이 특정 줄은 다음과 같습니다.

NAME="Debian GNU/Linux"

오른쪽의 따옴표를 주목하세요. Ubuntu에서도 사용할 수 있는 경우 name따옴표는 에 특별한 것이 아니기 때문에 에서도 문자 그대로 따옴표를 받게 됩니다 cut. 또 다른 문제는 문자열에 공백이 포함될 수 있다는 것입니다. 이 경우 토큰화가 문자열에서 따옴표가 없는 변수 확장에 도달 [ $name = "Ubuntu" ]하고 테스트에서 오류가 발생할 수 있습니다.

이러한 문제를 방지하려면 변수 확장을 인용하고 비교 문자열 주위에 리터럴 인용을 추가하십시오.

if [ "$name" = '"Ubuntu"' ]; then ...

또는 문자열의 시작과 끝에서 따옴표를 제거 name=${name#\"}; name=${name%\"}하고 여전히 quote 를 사용합니다 "$name".

답변3

이 특별한 경우에는 다음과 같이 스크립트를 단순화할 수 있습니다.

#!/bin/sh

if grep -q Ubuntu /etc/os-release; then
  echo "This should return"
else
  echo "This is wrong"
fi

grep, 이 -q옵션을 전달하면 아무것도 인쇄되지 않지만 문자열이 발견되면 코드 0으로 종료되고 그렇지 않으면 0이 아닌 코드로 종료됩니다. if결국 그것이 우리가 기대하는 것입니다.

답변4

단순한

$ grep -q Ubuntu /etc/os-release && echo "This should return" || echo "This is wrong"

또는

$ . /etc/os-release && echo "$NAME"

또는 lsb_release다음 명령을 사용할 수도 있습니다.

$ lsb_release -i -s

관련 정보