bash에서 인수를 옵션으로 만드는 방법은 무엇입니까?


13

9 개의 인수를 가진 아래 함수에서 :

SUM() { 
    echo "The sum is $(($1+$2+$3+$4+$5+$6+$7+$8+$9))"
}

다음 (3..9)에 대한 두 번째 인수를 선택적 인수 로 만들고 싶습니다 .

두 개의 인수로 함수를 호출하면 오류가 발생합니다.

SUM 3 8
bash: 3+8+++++++: syntax error: operand expected (error token is "+")

참고 BOLD : 첫 번째 인수와 두 번째 인수는 강제 인수 이며 기능에 대해 선택 사항이 아닙니다. 다음 인수에 대한 두 번째 인수 만 선택적이며 2 args 미만의 함수를 호출하면 함수가 결과를 반환하지 않아야합니다.

답변:


22

공백이있는 인수를 전달하지 않는 경우 :

sum() {  
[[ -n $2 ]] && echo $(( $(tr ' ' '+' <<<"$@") ))
}

효과:

$ sum 1 2 3
6

설명:

  1. <<<"some string""some string"입력 으로 만 피드 합니다. 이를 속기라고 생각하십시오 echo "some string" |. 이를 Here String 이라고합니다 .
  2. "$@"공백으로 구분 된 모든 위치 매개 변수로 확장됩니다. 와 같습니다 "$1 $2 ...".
  3. 따라서 tr ' ' '+' <<<"$@"출력 "$1+$2+$3..."은 outer에 의해 평가됩니다 $(( )).
  4. [[ -n $2 ]]두 번째 매개 변수가 비어 있지 않은지 테스트합니다. 으로 교체 할 수 [[ -n $2 ]] &&있습니다 [[ -z $2 ]] ||.

또 다른 방법:

sum() {
[[ -n $2 ]] && (IFS=+; echo $(( $* )))
}

설명:

  1. $*$@매개 변수가 공백으로 구분되지 않고 Internal Field Separator ( IFS) 의 첫 문자로 구분된다는 점을 제외하고 는 같습니다 . 를 사용하면 IFS=+"$ 1 + $ 2 + ..."로 확장됩니다. $ *와 $ @의 차이점무엇입니까?를 참조하십시오 .
  2. IFS메인 쉘이 영향을받지 않도록 서브 쉘 (주변 괄호에주의)을 설정 했습니다. IFS기본적으로 : \t\n(공백, 탭, 줄 바꿈)입니다. local변수 를 사용하는 대신 사용할 수 있습니다.

이제 귀하의 질문에 대답하십시오 :

모든 변수 또는 매개 변수에 기본값을 사용할 수 있습니다 . 어느 한 쪽:

SUM() { 
 echo "The sum is $(($1+$2+${3:-0}+${4:-0}+${5:-0}+${6:-0}+${7:-0}+${8:-0}+${9:-0}))" || false
}

또는:

SUM() { 
 echo "The sum is $(($1+$2+${3:=0}+${4:=0}+${5:=0}+${6:=0}+${7:=0}+${8:=0}+${9:=0}))" || false
}

6
맵시 있는! 나는 의견이 무의미한 칭찬과 감사를위한 것이 아니라는 것을 알고 있지만이 솔루션은 ... 사악합니다! :-)
zwets

17

shift운영자를 살펴보십시오 . 인수 2를 무시하고 인수 1을 버리고 위치 1 이상으로 이동합니다.

sum () {
    local total=0;
    while [ $# -gt 0 ]; do
        total=$(($total + $1))
        shift
    done
    echo $total
}

4

sum인수없이 호출 될 때 종료되는 재귀 정의를 사용할 수 있습니다 . 우리는 test인수없이 평가 한다는 사실을 이용 합니다 false.

sum () {
    test $1 && echo $(( $1 + $(shift; sum $@) )) || echo 0
}

3

이 시도:

SUM () {
 [ $# -lt "2" ] && return 1
 for par in $@; do
   local sum=`expr $sum + $par`
 done
 echo $sum
 return 0
}

SUM 3 4 5
SUM 3 4 5 1 1 1 1 2 3 4 5

12와 30이 출력됩니다.

$@매개 변수를 참조하고 매개 변수 $#수 (이 경우 3 또는 11)를 리턴합니다.

리눅스 redhat 4에서 테스트


2

작은 루프를 사용할 수 있습니다.

sum(){
    t=0;
    for i in "$@"; do t=$((t + i )); done
    echo $t;
}

개인적으로, 나는 그냥 perl또는 awk대신 사용 합니다.

sum(){
 echo "$@" | perl -lane '$s+=$_ for @F; print $s'
}

또는

sum(){
 echo "$@" | awk '{for(i=1; i<=NF; i++){k+=$i} print k}'
}

2

$ 1 ~ $ 9의 기본값으로 0을 사용하십시오.

SUM() { 
    echo "The sum is $((${1:-0}+${2:-0}+${3:-0}+${4:-0}+${5:-0}+${6:-0}+${7:-0}+${8:-0}+${9:-0}))"
}

보낸 사람 man bash:

${parameter:-word}
    Use Default Values. If parameter is unset or null, the expansion
    of word is substituted. Otherwise, the value of parameter is
    substituted.

예 :

$ SUM

합계는 0입니다

$ SUM 1 2 

합계는 3

$ SUM 1 1 1 1 1 1 1 1 1 

합계는 9


awk와 동일한 출력 :

SUM() {
  echo -e ${@/%/\\n} | awk '{s+=$1} END {print "The sum is " s}'
}

1

그것은 내가 시도하고 찾은 내 자신의 솔루션이기도합니다.

SUM() { 
    echo "The sum is $(($1+$2+$[$3]+$[$4]+$[$5]+$[$6]+$[$7]+$[$8]+$[$9]))"
 }

$ SUM 4 6 5
The sum is 15

그러나 @muru의 대답 은 좋습니다.


+1 : 빈 매개 변수를 0으로 평가하기 위해 두 개의 산술 확장 을 흥미롭게 사용 합니다.
muru

1
@muru 감사하지만이 경우 내 대답 은 9 개 이상의 인수를 사용하지 않으며 9 개 이상의 인수를 전달하기 위해 인수 그룹을 사용해야합니다. 완벽한 답변에 감사드립니다.
αғsнιη
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.