변수가 비어 있거나 공백 만 포함되어 있는지 테스트하려면 어떻게해야합니까?


240

다음 bash 구문 param은 비어 있지 않은지 확인합니다 .

 [[ !  -z  $param  ]]

예를 들면 다음과 같습니다.

param=""
[[ !  -z  $param  ]] && echo "I am not zero"

출력이없고 괜찮습니다.

그러나 param하나 이상의 공백 문자를 제외하고 비어있는 경우는 다릅니다.

param=" " # one space
[[ !  -z  $param  ]] && echo "I am not zero"

"0이 아님"이 출력됩니다.

공백 문자 만 포함 된 변수를 비어있는 것으로 간주하도록 테스트를 변경하려면 어떻게해야합니까?


4
보낸 사람 man test: -z STRING - the length of STRING is zero. 의 모든 공백을 제거 $param하려면 다음을 사용하십시오.${param// /}
dchirikov

6
WOW 간단한이없는 trim()내장 전혀 * nix에서 스크립트에 기능은? 아주 간단한 무언가를 달성하기위한 많은 다른 해킹 ...
ADTC

6
@ADTC $ (sed 's / ^ \ s + | \ s + $ // g'<<< $ string) 나에게 충분히 간단 해 보입니다. 왜 바퀴를 재발 명합니까?
jbowman

3
더 빛날 수 있기 때문에
Inversus

1
그 점에 주목하면 [[ ! -z $param ]]됩니다 test ! -z $param.
노아 서스 먼

답변:


292

먼저 -z테스트 는 다음을 명시 적으로 수행합니다.

문자열의 길이는 0입니다

즉, 공백 만 포함하는 문자열 은 길이가 0이 아니기 때문에 true 가되어서는 안됩니다-z .

패턴 대체 매개 변수 확장을 사용하여 변수에서 공백을 제거하는 것이 좋습니다 .

[[ -z "${param// }" ]]

이렇게하면 param변수가 확장되고 패턴 (단일 공백) 의 모든 일치 항목이 아무것도없는 것으로 대체 되므로 공백 만있는 문자열은 빈 문자열로 확장됩니다.


그 작동 방식핵심 은로 ${var/pattern/string}가장 긴 일치 항목을 pattern로 대체 한다는 것 입니다 string. (위와 같이) pattern시작 하면 모든 일치 항목을 /대체 합니다 . 교체가 비어 있기 때문에 최종 값 /string값을 생략 할 수 있습니다 .

$ {매개 변수 / 패턴 / 문자열}

패턴은 단지 파일 이름 확장에서 같은 패턴을 생성하기 위해 확장된다. 매개 변수 가 확장되고 해당 값에 대한 가장 긴 패턴 일치 가 string 으로 대체됩니다 . 경우 패턴이 '/'로 시작, 모든 일치하는 패턴 으로 대체됩니다 문자열 . 일반적으로 첫 번째 일치 항목 만 교체됩니다. ... 문자열 이 null 인 경우 패턴 일치 가 삭제되고 / 다음 패턴 이 생략 될 수 있습니다.

그런 다음 모든 ${param// }공백을 삭제합니다.

참고로 존재하지만 ksh(이 발생한 위치) zshbash해당 구문 POSIX 아니며에서 사용되지 않으며, sh스크립트.


sed그들이 말한 사용 ... 그들이 말한 echo변수 ...
mikezter

1
흠. 이 경우 ${var/pattern/string}그것은 안 [[ -z ${param/ /} ]]문자열이 될 후 패턴 아무것도 될 수있는 슬래시 사이의 공간?
Jesse Chisholm 17 년

@JesseChisholm "대체가 비어 있기 때문에 최종 / 및 문자열 값을 생략 할 수 있습니다"; " 문자열 이 null 인 경우 패턴 일치 가 삭제되고 / 다음 패턴 이 생략 될 수 있습니다."
Michael Homer

6
대답 @MichaelHomer [[ -z "${param// }" ]](가)처럼 확실히 보이는 pattern비어하고는 replacement string하나의 공간입니다. 아! 나는 지금 if pattern begins with a slash그 부분을 놓쳤다는 것을 알았습니다. 따라서 패턴이 / 있고 문자열이 꺼져 있으므로 비어 있습니다. 감사.
Jesse Chisholm

bash 참고 : set -o nounset (set -u)에서 실행 중이고 param이 설정되지 않은 경우 (널 또는 공백으로 채워지지 않은 경우) 바인딩되지 않은 변수 오류가 발생합니다. (set + u; .....)는이 테스트를 면제합니다.
Brian Chrisman

31

문자열에 인증 된 세트의 문자 만 포함되어 있는지 확인하는 쉬운 방법은 인증되지 않은 문자가 있는지 테스트하는 것입니다. 따라서 문자열에 공백 만 포함되어 있는지 테스트하는 대신 문자열에 공백 이외의 문자가 포함되어 있는지 테스트하십시오. bash, ksh 또는 zsh에서 :

if [[ $param = *[!\ ]* ]]; then
  echo "\$param contains characters other than space"
else
  echo "\$param consists of spaces only"
fi

“공백으로 만 구성”에는 빈 (또는 설정되지 않은) 변수의 경우가 포함됩니다.

공백 문자를 테스트 할 수 있습니다. [[ $param = *[^[:space:]]* ]]로케일 설정 또는 공백 [[ $param = *[$' \t\n']* ]], 탭 또는 줄 바꿈과 같이 테스트 하려는 공백 문자 목록을 사용하는 데 사용 하십시오 .

=내부 [[ … ]]가 있는 패턴과 문자열을 일치시키는 것은 ksh 확장자입니다 (bash 및 zsh에도 있음). Bourne / POSIX 스타일에서 case구문을 사용하여 문자열을 패턴과 일치 시킬 수 있습니다 . 표준 쉘 패턴 은 대부분의 정규 표현식 구문에서와 !달리 문자 세트를 무효화하는 데 사용 됩니다 ^.

case "$param" in
  *[!\ ]*) echo "\$param contains characters other than space";;
  *) echo "\$param consists of spaces only";;
esac

공백 문자를 테스트하기 위해 $'…'구문은 ksh / bash / zsh에만 적용됩니다. 스크립트에 문자를 문자 그대로 삽입하거나 (백 슬래시 + 줄 바꿈이 아무 것도 확장되지 않기 때문에 줄 바꿈은 따옴표 안에 들어가야합니다.)

whitespace=$(printf '\n\t ')
case "$param" in
  *[!$whitespace]*) echo "\$param contains non-whitespace characters";;
  *) echo "\$param consists of whitespace only";;
esac

이것은 거의 우수하지만 아직 질문에 대답하지 않습니다. 현재 설정되지 않거나 비어있는 쉘 변수와 공백 만 포함하는 변수 의 차이점을 알 수 있습니다. 내 제안을 받아 들일 경우 아직 설정되지 않은 쉘 변수를 명시 적으로 테스트하는 다른 답변에 의해 수렴되지 않은 매개 변수 확장 양식을 추가 할 것입니다. ${var?not set}즉, 테스트를 통과하고 생존하면 일치하는 변수 *) case가 결정적인 영향을 미치게됩니다 예를 들어 대답하십시오.
mikeserv

보정 -이 사실 원래 묻는 질문에 대답,하지만이 이후는 근본적으로 질문의 의미를 변경하기 때문에 답을 무효화하는 방식으로 편집되었습니다.
mikeserv

당신은 필요 [[ $param = *[!\ ]* ]]에서 mksh.
Stéphane Chazelas

20

POSIXly :

case $var in
  (*[![:blank:]]*) echo '$var contains non blank';;
  (*) echo '$var contains only blanks or is empty or unset'
esac

blank , non-blank , empty , unset 을 구별하려면 다음을 수행하십시오.

case ${var+x$var} in
  (x) echo empty;;
  ("") echo unset;;
  (x*[![:blank:]]*) echo non-blank;;
  (*) echo blank
esac

[:blank:]가로 간격 문자 (ASCII의 공백 및 탭) 용이지만 로케일에 더 많은 문자가있을 수 있습니다. 일부 시스템에는 중단되지 않는 공백 (사용 가능한 경우)이 포함되며 일부는 그렇지 않습니다. 당신은뿐만 아니라 (개행 문자 또는 용지 공급 등) 세로 간격 문자를 원하는 경우, 교체 [:blank:]와 함께 [:space:].


POSIXly는 (아마도 더 나은) 대시와 함께 작동하기 때문에 이상적입니다.
Ken Sharp

zsh와에 문제가있는 것 [![:blank:]]그 인상은 :b무효 수정합니다. 에서 shksh모방,이 이벤트를 발생 찾을 수 없습니다[
cuonglm

@cuonglm, 무엇을 시도 했습니까? var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'괜찮습니다. 발견되지 않은 이벤트는 대화식 쉘 전용입니다.
Stéphane Chazelas

@ StéphaneChazelas : 아, 맞습니다. 대화식 쉘로 시도했습니다. :b잘못된 수정은 약간 이상하다.
cuonglm 2016 년

1
@FranklinYu는 OS에 / X가 sh되는 bash빌드 --enable-xpg-echo-default하고 --enable-strict-posix-default있으므로 (유닉스 포함 호환로서 echo '\t'탭 출력).
Stéphane Chazelas

4

훌륭한 스크립팅 언어로 된 스크립트 대신 쉘 스크립트를 작성하는 유일한 이유 는 극단적 인 이식성이 가장 중요한 문제이기 때문입니다. 레거시는 /bin/sh당신이 당신이 확신 할 수있는 유일한 일이지만 예를 들어 펄은 배쉬 이상의 사용 가능한 크로스 플랫폼이 될 것으로 보인다. 따라서 보편적 이지 않은 기능을 사용하는 쉘 스크립트를 작성하지 말고 POSIX.1-2001 이전에 여러 독점 유닉스 벤더가 쉘 환경을 동결했음을 명심하십시오 .

이 테스트를 수행하는 휴대용 방법이 있지만 다음을 사용해야합니다 tr.

[ "x`printf '%s' "$var" | tr -d "$IFS"`" = x ]

$IFS편리하게 기본값 은 공백, 탭 및 줄 바꿈입니다.

( printf내장 자체는 현명하게 이식 가능하지만, 그것에 의존하는 것은 echo당신의 변형을 알아내는 것보다 훨씬 덜 번거 롭습니다 .)


1
약간 복잡합니다. 문자열에 특정 문자가 포함되어 있는지 테스트하는 일반적인 이식 방법은 입니다case .
Gilles

@Gilles 나는 case비어 있거나 공백 문자 포함하는 문자열을 감지하기 위해 glob 를 작성할 수 있다고 생각하지 않습니다 . (정규식으로는 쉽지만 정규식 case은 사용하지 않습니다. 줄 바꿈에 신경
쓰면

1
나는 질문에 요구 한 것이기 때문에 대답에 예를 들어 공백을주었습니다. 공백 문자를 테스트하는 것도 마찬가지로 쉽습니다 case $param in *[![:space:]]*) …. IFS문자 를 테스트 하려면 패턴을 사용할 수 있습니다 *[$IFS]*.
Gilles

1
정말에서 @mikeserv 심각하게 방어 스크립트는 명시 적으로 IFS를 설정 <space><tab><newline>시작 부분에 다음 다시 손을 대지 마십시오. 나는 그것이 방해가 될 것이라고 생각했다.
zwol

1
패턴의 변수에 관해서는 모든 Bourne 버전과 모든 POSIX 셸에서 작동한다고 생각합니다. 케이스 패턴을 감지하고 변수 확장을 끄려면 추가 코드가 필요하며 그렇게 할 이유를 생각할 수 없습니다. .profile많은 Bourne 쉘에 의해 실행 된 인스턴스가 몇 개 있습니다. 물론 기본값이 아닌 특정 값 (빈 (또는 설정되지 않은), 또는로 시작 하거나로 시작 )이있는 [$IFS]경우 의도 한 작업을 수행하지 않습니다 . IFS]!^
Gilles

4
if [[ -n "${variable_name/[ ]*\n/}" ]]
then
    #execute if the the variable is not empty and contains non space characters
else
    #execute if the variable is empty or contains only spaces
fi

이것은 단일 공백이 아닌 공백 문자를 제거합니다. 감사
Alexander Mills

0

변수가 비어 있거나 공백을 포함하는지 테스트하려면 다음 코드를 사용할 수도 있습니다.

${name:?variable is empty}

2
"또는 공백 포함"이 사실이 아니기 때문에 귀하의 답변이 다운 보트 된 것 같습니다.
Bernhard

조심하십시오-현재 쉘을 죽입니다. (: $ {subshell?})에 넣는 것이 좋습니다. 또한-stderr에 기록됩니다-아마도 리디렉션을 원할 것입니다. 그리고 가장 중요한 변수의 실제 값으로 평가하는이 해제 또는 null가 아닌 경우. 거기에 명령이 있으면 방금 명령을 실행 한 것입니다. 에 테스트를 실행하는 것이 가장 좋습니다 :.
mikeserv

껍질을 죽이는 방법. 그리고 u는 또한 정의 첫째,이 테스트 할 수 있습니다 name=aaaa다음이 명령을 실행 echo ${name:?variable is empty}이 변수 이름의 값을 출력 지금이 명령 실행 echo ${name1:?variable is empty}이 인쇄됩니다 변수가 비어 : 이름 1 : -SH
pratik

예 - echo ${name:?variable is empty}에 평가합니다 하나 $name의 null 이외의 값을 또는 그것은 쉘을 죽일 것이다. 그래서 같은 이유로 당신도 그렇게 prompt > $randomvar하지 말아야합니다 ${var?}– 명령이 있다면, 아마도 실행될 것입니다 – 그리고 당신은 그것이 무엇인지 모릅니다. 대화식 쉘을 종료하지 않아도되므로 종료하지 않아도됩니다. 여전히 몇 가지 테스트를 보려면 여기에 많은 테스트가 있습니다. . 이것은 오래 걸리지 않습니다 ...
mikeserv

0

변수가 설정되지 않았 는지 테스트하려면 비어 있거나 (널 값이 있음) 공백 만 포함합니다.

 [ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"

설명:

  • 확장은 ${param%%[! ]*}첫 번째 비 공간에서 끝까지 제거됩니다.
  • 그것은 앞 공간 만 남습니다.
  • 다음 확장은 변수에서 선행 공백을 제거합니다.
  • 결과가 비어있는 경우 변수는 시작하기 위해 비어있었습니다.
  • 또는 변수가 비어 있지 않은 경우 선행 공백을 제거하면 변수가 비워집니다.
  • 결과가 비어 있으면 -zecho empty.

위의 내용은 POSIX와 호환되며 모든 Bourne 자손에서 실행됩니다.

이를 탭으로 확장하려면 명시 적 탭을 포함하십시오.

 [ -z "${param#"${param%%[!     ]*}"}" ] && echo "empty"

또는 제거해야 할 문자가있는 변수를 사용하십시오.

 var=$' \t'   # in ksh, bash, zsh
 [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"

또는 POSIX "문자 클래스 표현식"을 사용할 수 있습니다 (공백은 공백과 탭을 의미 함).

 [ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"

그러나 mksh, lksh 및 posh에서는 실패합니다.


-1

이 시도:

$ [[ -z \`echo $n\` ]] && echo zero

zero
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.