Bash의 삼항 연산자 (? :)


442

이런 식으로 할 수있는 방법이 있습니까

int a = (b == 5) ? c : d;

배쉬를 사용합니까?


1
@dutCh의 답변에 따르면 bash"삼항 연산자"와 비슷한 것이 있지만 bash이를 "조건부 연산자"라고합니다 ( "산술 평가"섹션 expr?expr:expr참조 man bash). 마음에 계속 bash"조건 연산자는"까다 롭습니다 일부 개는있다.
Trevor Boyd Smith

Bash에는 정수에 대한 삼항 연산자가 있으며 산술 표현식 내에서 작동합니다 ((...)). 쉘 산술을 참조하십시오 .
codeforester

1
@codeforester가 언급했듯이 삼항 연산자는 산술 확장 $(( ))및 산술 평가와 함께 작동합니다 (( )). 도 참조하십시오 https://mywiki.wooledge.org/ArithmeticExpression.
카이

답변:


490

삼항 연산자 ? :if/else

case "$b" in
 5) a=$c ;;
 *) a=$d ;;
esac

또는

 [[ $b = 5 ]] && a="$c" || a="$d"

103
참고 그 =문자열 평등에 대한 연산자 테스트가 아닌 숫자 평등 (즉, [[ 05 = 5 ]]거짓). 숫자 비교를 원하면 -eq대신 사용하십시오.
Gordon Davisson

10
if/then/else
vol7ron의

15
삼항 연산자 효과를 얻기 위해 단락 동작을 활용하는 천재적인 방법입니다. :) :) :)
mtk

6
왜 [[와]]? 다음과 같이 작동합니다 : [$ b = 5] && a = "$ c"|| a = "$ d"
kdubs

83
cond && op1 || op2구조는 고유의 버그가 다음과 같은 경우 op1어떤 이유에서 0이 아닌 종료 상태가 결과는 자동으로 될 것입니다 op2. if cond; then op1; else op2; fi한 줄이며 결함이 없습니다.
ivan_pozdeev

375

암호:

a=$([ "$b" == 5 ] && echo "$c" || echo "$d")

58
이것은 다른 것보다 낫습니다 ... 3 차 연산자에 대한 요점은 연산자라는 것입니다. 따라서 적절한 컨텍스트가 표현식에 있으므로 값을 반환해야합니다.
nic ferrier

2
이것이 가장 간결한 방법입니다. with echo "$c"가있는 부분 이 별칭이있는 여러 줄로 된 명령 (예 echo 1; echo 2:)이면 괄호로 묶어야합니다.
Matt

2
또한 테스트 된 명령의 출력도 캡처합니다 (예,이 경우에는 어떤 것도 생성하지 않음을 "알고 있습니다").
ivan_pozdeev

8
이 연산자 체인 은 이후 명령 &&이 0이 아닌 종료 상태를 갖지 않는다고 긍정적 인 경우에만 삼항 연산자처럼 작동 합니다. 그렇지 않으면 성공하지만 실패 하면 a && b || c "예기치 않게"실행 c됩니다 . ab
chepner

155

조건이 단순히 변수가 설정되어 있는지 확인하는 경우 더 짧은 형식이 있습니다.

a=${VAR:-20}

if 가 설정 되면 a값을 할당하고 , 그렇지 않으면 기본값을 할당합니다 . 이것은 표현식의 결과 일 수도 있습니다.VARVAR20

alex가 주석에서 언급 한 것처럼이 방법을 기술적으로 "매개 변수 확장"이라고합니다.


6
하이픈이 포함 된 문자열 매개 변수를 전달하는 경우 따옴표를 사용해야했습니다. a=${1:-'my-hyphenated-text'}
saranicole

1
게으른에 대한 링크 -그냥 대체 ( :-) 보다 추가 연산자가 있습니다
Justin Wrobel

10
@JustinWrobel-불행히도 같은 구문이 없습니다 ${VAR:-yes:-no}.
Ken Williams

76
if [ "$b" -eq 5 ]; then a="$c"; else a="$d"; fi

cond && op1 || op2다른 답변에서 제안 표현은 고유의 버그가 다음과 같은 경우 op1제로가 아닌 종료 상태가, op2자동으로 결과가된다; -e모드 에서도 오류가 발생하지 않습니다 . 그래서, 그 표현은 경우에 사용하는 유일한 안전 op1하지 않을 수 있습니다 (예를 들어 :, true분열과 OS 호출)처럼 (실패 할 수있는 모든 작업없이 내장, 또는 변수 할당하는 경우).

""따옴표를 참고하십시오 . 첫 번째 쌍 $b은 공백이거나 공백이있는 경우 구문 오류를 방지합니다 . 다른 것들은 모든 공백이 단일 공백으로 변환되는 것을 막을 것입니다.


1
나는 또한 접두사를 보았습니다 [ "x$b" -eq "x" ]. 빈 문자열을 구체적으로 테스트하는 데 사용 되었다고 생각 합니다. zsh (zshexpn 맨 페이지의 'PARAMETER EXPANSION')에서 사용하는 구문을 사용하고 싶지만 이식성에 대해 잘 모릅니다.
John P


46
(( a = b==5 ? c : d )) # string + numeric

31
이것은 좋다 숫자 비교와 과제,하지만 당신은 문자열 비교와 과제 .... 위해 그것을 사용하는 경우는 예기치 않은 결과를 줄 것이다 (( ))취급 어느 / 모든 문자열0
Peter.O

3
이것은 또한 쓰여질 수있다 :a=$(( b==5 ? c : d ))
joeytwiddle

33
[ $b == 5 ] && { a=$c; true; } || a=$d

이렇게하면 || 다음 부분을 실행하지 않아도됩니다. &&와 || 사이의 코드가 실수로 우연히 실패합니다.


이것은 여전히 -e모드 에서 오류를 잡을 수 없습니다 : (set -o errexit; [ 5 == 5 ] && { false; true; echo "success"; } || echo "failure"; echo $?; echo "further on";)->success 0 further on
ivan_pozdeev

2
외부 프로그램 을 저장 하는 :대신 bulit-in을 사용하십시오 . trueexec
Tom Hale

@ivan_pozdeev &&.. 를 사용하는 방법이 ||있습니까? 그리고 그들 사이에서 여전히 실패한 명령을 잡을 수 있습니까?
Tom Hale

2
@TomHale No. &&||정의상 전체 명령에 적용됩니다. 따라서 결합 방법에 관계없이 두 개의 명령이 앞에 있으면 명령 중 하나에 만 적용 할 수 없으며 다른 명령에는 적용 할 수 없습니다. 당신은 할 수 에뮬레이션 if/ then/ else플래그 변수와 논리를, 그러나이 있다면 왜 귀찮게 if/ then/ else적절한?
ivan_pozdeev

14

하자의 명령에서 지원하는 대부분의 사람이 필요 기본 연산자 :

let a=b==5?c:d;

당연히 이것은 변수 할당에만 작동합니다. 다른 명령을 실행할 수 없습니다.


24
그것은, 그래서 산술 식에 대해서만 유효합니다 ((...)) 정확히 동일합니다
drAlberT

13

다음은 한 번만 할당 할 변수 만 지정해야하는 또 다른 옵션이며, 할당이 문자열인지 숫자인지는 중요하지 않습니다.

VARIABLE=`[ test ] && echo VALUE_A || echo VALUE_B`

그냥 생각이야 :)


주요 단점은의 stdout을 캡처하는 것입니다 [ test ]. 따라서이 구문은 명령이 stdout에 아무것도 출력하지 않는다는 것을 "알고"있는 경우에만 사용하는 것이 안전합니다.
ivan_pozdeev

또한 stackoverflow.com/questions/3953645/ternary-operator-in-bash/… 와 동일하며 내부에서 따옴표를 인용하고 이스케이프해야합니다. 공간 허용 버전은 다음과 같습니다 VARIABLE="`[ test ] && echo \"VALUE_A\" || echo \"VALUE_B\"`".
ivan_pozdeev

8

다음은 내 사용 사례에서 작동하는 것 같습니다.

$ tern 1 YES NO                                                                             
YES

$ tern 0 YES NO                                                                             
NO

$ tern 52 YES NO                                                                            
YES

$ tern 52 YES NO 52                                                                         
NO

다음과 같이 스크립트에서 사용할 수 있습니다.

RESULT=$(tern 1 YES NO)
echo "The result is $RESULT"

세 개 한 세트

function show_help()
{
  echo ""
  echo "usage: BOOLEAN VALUE_IF_TRUE VALUE_IF_FALSE {FALSE_VALUE}"
  echo ""
  echo "e.g. "
  echo ""
  echo "tern 1 YES NO                            => YES"
  echo "tern 0 YES NO                            => NO"
  echo "tern "" YES NO                           => NO"
  echo "tern "ANY STRING THAT ISNT 1" YES NO     => NO"
  echo "ME=$(tern 0 YES NO)                      => ME contains NO"
  echo ""

  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$3" ]
then
  show_help
fi

# Set a default value for what is "false" -> 0
FALSE_VALUE=${4:-0}

function main
{
  if [ "$1" == "$FALSE_VALUE" ]; then
    echo $3
    exit;
  fi;

  echo $2
}

main "$1" "$2" "$3"

7
매우 설명이 필요합니다. 매우 완벽합니다. 매우 장황하다. 내가 좋아하는 세 가지. ;-)
Jesse Chisholm

2
tern강타의 일부? Mac에는없는 것 같습니다
비극성

4
안녕하세요 @ 太極 者 無極 而 生-bash 스크립트의 이름입니다. 위의 "tern"섹션을 "tern"이라는 파일에 저장 한 다음 chmod 700 tern동일한 폴더에서 실행 하십시오. 이제 tern터미널에서 명령을 내릴 수 있습니다
Brad Parks

8

삼항 연산자를 위해 Shell Scripting에서 다음 세 가지 방법을 사용할 수 있습니다.

    [ $numVar == numVal ] && resVar="Yop" || resVar="Nop"

Or

    resVar=$([ $numVar == numVal ] && echo "Yop" || echo "Nop")

Or

    (( numVar == numVal ? (resVar=1) : (resVar=0) ))

이것은 실제로 (이 세 가지 예 중 첫 번째와 두 번째 예)이 질문 IMHO에 가장 적합한 답변입니다.
netpoetica

6

bash에는 삼항 조건에 대해 매우 유사한 구문이 있습니다.

a=$(( b == 5 ? 123 : 321  ))

불행히도, 내가 아는 한 숫자로만 작동합니다.


5
(ping -c1 localhost&>/dev/null) && { echo "true"; } || {  echo "false"; }

4

비슷한 문법을 ​​원한다면 이것을 사용할 수 있습니다

a=$(( $((b==5)) ? c : d ))

이것은 정수에서만 작동합니다. 당신은 더 간단하게 쓸 수 있습니다 a=$(((b==5) ? : c : d))- $((...))우리가 다른 변수에 연산의 결과를 할당 할 경우에만 필요합니다.
codeforester 2018 년

2

몇 가지 옵션이 있습니다.

1- 그렇다면 한 줄로 사용하면 가능합니다.

if [[ "$2" == "raiz" ]] || [[ "$2" == '.' ]]; then pasta=''; else pasta="$2"; fi

2- 다음과 같은 함수를 작성하십시오.

 # Once upon a time, there was an 'iif' function in MS VB ...

function iif(){
  # Echoes $2 if 1,banana,true,etc and $3 if false,null,0,''
  case $1 in ''|false|FALSE|null|NULL|0) echo $3;;*) echo $2;;esac
}

이와 같이 스크립트 내부에서 사용하십시오

result=`iif "$expr" 'yes' 'no'`

# or even interpolating:
result=`iif "$expr" "positive" "negative, because $1 is not true"` 

3- 대답에서 영감을 얻은보다 유연하고 한 줄 사용은 다음과 같습니다.

 case "$expr" in ''|false|FALSE|null|NULL|0) echo "no...$expr";;*) echo "yep $expr";;esac

 # Expression can be something like:     
   expr=`expr "$var1" '>' "$var2"`

2

일반적인 해결책은 다음과 같습니다.

  • 문자열 테스트에서도 작동
  • 오히려 표현 같은 느낌
  • 상태가 실패 할 때 미묘한 부작용을 피합니다

수치 비교 테스트

a = $(if [ "$b" -eq 5 ]; then echo "$c"; else echo "$d"; fi)

문자열 비교로 테스트

a = $(if [ "$b" = "5" ]; then echo "$c"; else echo "$d"; fi)


1

이것은 Vladimir의 훌륭한 답변 과 매우 비슷 합니다. "삼항"이 "true, string, false, empty"인 경우 간단하게 수행 할 수 있습니다.

$ c="it was five"
$ b=3
$ a="$([[ $b -eq 5 ]] && echo "$c")"
$ echo $a

$ b=5
$ a="$([[ $b -eq 5 ]] && echo "$c")"
$ echo $a
it was five

1

대답 : int a = (b == 5) ? c : d;

그냥 써:

b=5
c=1
d=2
let a="(b==5)?c:d"

echo $a # 1

b=6;
c=1;
d=2;
let a="(b==5)?c:d"

echo $a # 2

"expression"은 $ ((expression))과 같습니다.


0

배열을 사용하는 문자열 지향 대안 :

spec=(IGNORE REPLACE)
for p in {13..15}; do
  echo "$p: ${spec[p==14]}";
done

어떤 출력 :

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