bash에서 $ #는 무엇을 의미합니까?


26

instance라는 파일에 스크립트가 있습니다.

echo "hello world"
echo ${1}

그리고 내가 다음을 사용 하여이 스크립트를 실행할 때 :

./instance solfish

나는이 출력을 얻는다 :

hello world
solfish

그러나 내가 달릴 때 :

echo $# 

"0"이라고 표시되어 있습니다. 왜? 무슨 $#뜻 인지 모르겠습니다 .

설명해주세요.


10
왜 뛰니 $#? 무엇을 달성하고 싶습니까? 이 명령은 어디서 얻었습니까? 전혀 관련이 없습니다.
Pilot6

7
이 경우 @ Pilot6은 변수의 의미를 묻습니다.이 경우는 구체적이지 않으므로 op가 정보를 제공 해야하는 이유는 무엇입니까?
ADDB

21
@solfish Pilot이 기대했던 것을 이해하려고합니다. 당신은 당신이 달렸다고 말했고 echo $#그것은 0정상적인 것입니다. 당신은 이것에 놀랐지 만, 당신이 무엇을 기대했는지, 왜 놀랐는지 설명하지 않습니다. 따라서 귀하가 기대하는 바를 설명하면 더 나은 답변을 드릴 수 있습니다. 당신이 할 것이라고 생각한 echo $#것. 당신이 실행 ./instance solfish하고 ./instance포함 echo $#하면 인쇄 1되지 않을 것 0입니다.
terdon


1
Java는 또한 argc를 사용하지 않습니다.
JakeRobb

답변:


66

$#bash인수의 수 (위치 매개 변수)로 확장 되는 특수 변수입니다 . 즉, 인수 $1, $2 ...가 쉘에 직접 전달 된 경우 (예 : in) 해당 스크립트 또는 쉘에 전달됩니다 bash -c '...' .....

이것은 argcC 와 비슷합니다 .


아마도 이것은 분명해질 것입니다 :

$ bash -c 'echo $#'
0

$ bash -c 'echo $#' _ x
1

$ bash -c 'echo $#' _ x y
2

$ bash -c 'echo $#' _ x y z
3

참고 것으로는 bash -c0부터 시작하여 다음 명령 후 인수를 취하는 ( $0, 기술적으로, 그것은 단지 bash당신이 설정시키기의의 방법으로 $0정말로 인수,) 그래서 _그냥 자리로 여기에 사용된다; 실제 인수는 x( $1), y( $2) 및 z( $3)입니다.


마찬가지로 다음과 같은 script.sh경우 스크립트 (가정 )에서

#!/usr/bin/env bash
echo "$#"

그런 다음에 할 때 :

./script.sh foo bar

스크립트는 2를 출력합니다; 마찬가지로,

./script.sh foo

1을 출력합니다.


1
이 답변이 잘못된 것이라고 생각합니다. $ #는 인수 배열의 최대 색인입니다. 하나의 인수를 제공하면 $ 0에 사용할 수 있으며 $ #의 값은 0입니다. 두 개의 인수를 제공하면 $ 0과 $ 1이되고 $ #의 값은 1이됩니다.
JakeRobb

1
또한을 사용할 때 bash -c실행 가능한 쉘 스크립트를 실행하는 경우와 동작이 다릅니다. 후자의 경우 인덱스 0의 인수가이를 호출하는 데 사용되는 쉘 명령이기 때문입니다. 따라서이 답변을 해결하는 방법은을 사용하는 대신 스크립트를 파일로 실행하도록 변경 bash -c하는 것입니다. 그 이유는 asker가 수행 한 방식이기 때문입니다.
JakeRobb

1
@JakeRobb 아니요. 스크립트의 $0경우 스크립트 자체가됩니다. 인수는입니다 $1, $2, $3.... bash -c비 대화식 사용을위한 의도와 동작이 다르며 명령 다음에 나오는 인수는에서 시작됩니다 $0.
heemayl

5
@JakeRobb 당신은 나를 깎아 냈습니다. 하나의 인수를 주면 $ 0에서 사용할 수 있으며 $ #의 값은 0 입니다. 이것은 잘못된 것입니다.
heemayl

2
args를 보는 완전한 프로그램을에 넣는 경우 , 0 번째 arg의 필러로 의미있는 이름을 bash -c전달해야합니다 bash. bash -c 'echo "$@"' foo bar를 포함하지 않기 bar때문에 항상 인쇄합니다 . "$ 0 인수 중 하나를 만들어"하지 않습니다, 그것은 단지 세트 "$ 0"으로 당신과 함께 프로그램 실행 같은 방법으로 당신을 수 있습니다 시스템 호출 또는 0 번째 인수를 오버라이드 (override)의 쉘 방법. "인수 중 하나"로 간주해서는 안됩니다. "$@"$0bash -cexecve$0
Peter Cordes

17

echo $# 스크립트의 위치 매개 변수 수를 출력합니다.

아무것도 없으므로 0을 출력합니다.

echo $# 별도의 명령이 아니라 스크립트 내에서 유용합니다.

다음과 같은 일부 매개 변수를 사용하여 스크립트를 실행하면

./instance par1 par2

echo $#스크립트가 출력 2에 위치.


6
영업의 예를 들어 당신이 라인을 추가하면 echo $#실행 스크립트와보다 다시 ./instance solfish당신과 함께 추가 출력 라인을 얻어야한다 1당신이 1 개 매개 변수를 제공하기 때문에
derHugo

14

$#일반적으로 매개 변수가 전달되도록 bash 스크립트에서 사용됩니다. 일반적으로 스크립트 시작 부분에서 매개 변수를 확인합니다.

예를 들어 다음은 오늘 작업 한 스크립트의 스 니펫입니다.

if [[ $# -ne 1 ]]; then
    echo 'One argument required for file name, e.g. "Backup-2017-07-25"'
    echo '.tar will automatically be added as a file extension'
    exit 1
fi

요약 $#하면 스크립트에 전달 된 매개 변수의 수를보고합니다. 귀하의 경우 매개 변수를 전달하지 않았으며보고 된 결과는 0입니다.


#배쉬의 다른 용도

#종종 발생 횟수 또는 가변 길이를 계산하는 떠들썩한 파티에서 사용된다.

문자열의 길이를 찾으려면

myvar="some string"; echo ${#myvar}

보고: 11

배열 요소 수를 찾으려면

myArr=(A B C); echo ${#myArr[@]}

보고: 3

첫 번째 배열 요소의 길이를 찾으려면

myArr=(A B C); echo ${#myArr[0]}

반환 값 : 1( A배열은 0부터 시작하는 인덱스 / 첨자를 사용하므로, 길이는 0입니다.)


$# -ne 1? 왜 그렇지 $# -le 0않습니까?
패트릭 Trentin

@PatrickTrentin 두 개 이상의 매개 변수를 전달하지 않기를 바랍니다. 선장이 "10 월 붉은"에서 말한 것처럼 : "그냥 하나".
WinEunuuchs2Unix

그런 다음 오류 메시지에서 "정확히 하나의 인수가 필요합니다 ..."
Patrick Trentin

@PatrickTrentin 오류 메시지는 하나의 인수 사용법의 예에서 스크립트가 사용되는 방식을 설명합니다. 또한 백업 스크립트는 cron.daily에
WinEunuuchs2Unix

그것이 어떻게 관련이 있는지 모르겠습니다. 어쨌든 건배.
Patrick Trentin

10

$# 인수의 수이지만 함수에서 다를 수 있음을 기억하십시오.

$#스크립트, 쉘 또는 쉘 함수에 전달 된 위치 매개 변수의 수입니다 . 쉘 함수가 실행되는 동안 위치 매개 변수가 함수의 인수로 임시 대체 되기 때문 입니다. 이를 통해 함수는 자체 위치 매개 변수를 승인하고 사용할 수 있습니다.

이 스크립트 는 함수 3자체 "$#"가 함수에 f전달 된 인수 수로 확장 되기 때문에 스크립트 자체에 전달 된 인수 수에 관계없이 항상를 인쇄 합니다.

#!/bin/sh

f() {
    echo "$#"
}

f a b c

쉘 함수에서 위치 매개 변수의 작동 방식에 익숙하지 않은 경우 다음과 같은 코드가 예상대로 작동하지 않기 때문에 중요합니다.

#!/bin/sh

check_args() { # doesn't work!
    if [ "$#" -ne 2 ]; then
        printf '%s: error: need 2 arguments, got %d\n' "$0" "$#" >&2
        exit 1
    fi
}

# Maybe check some other things...
check_args
# Do other stuff...

에서 check_args, $#해당 스크립트에 항상 0입니다 기능 자체에 전달 된 인수의 수를 확장합니다.

쉘 기능에서 이러한 기능을 원한다면 다음과 같이 작성해야합니다.

#!/bin/sh

check_args() { # works -- the caller must pass the number of arguments received
    if [ "$1" -ne 2 ]; then
        printf '%s: error: need 2 arguments, got %d\n' "$0" "$1" >&2
        exit 1
    fi
}

# Maybe check some other things...
check_args "$#"

이것은 함수 외부$# 로 확장 되어 위치 매개 변수 중 하나로 함수에 전달 되기 때문에 작동합니다 . 함수 내 에서 일부 스크립트에 포함되지 않고 쉘 함수에 전달 된 첫 번째 위치 매개 변수로 확장됩니다.$1

따라서, 같은 $#특수 매개 변수 $1, $2등뿐만 아니라, $@하고 $*, 또한이 기능으로 확장되는 함수에 전달 된 인수와 관련. 그러나 함수 이름으로 변경 $0되지 않으므로 품질 오류 메시지를 생성하는 데 계속 사용할 수 있습니다.

$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3

마찬가지로, 하나의 함수를 다른 함수 안에 정의하면 확장이 수행되는 가장 안쪽 함수에 전달 된 위치 매개 변수를 사용하는 것입니다.

#!/bin/sh

outer() {
    inner() {
        printf 'inner() got %d arguments\n' "$#"
    }

    printf 'outer() got %d arguments\n' "$#"
    inner x y z
}

printf 'script got %d arguments\n' "$#"
outer p q

이 스크립트를 호출 nested하고 (실행 후 chmod +x nested) 실행했습니다.

$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments

예, 알아요 "1 개의 인자"는 복수형 버그입니다.

위치 매개 변수도 변경할 수 있습니다.

스크립트를 작성하는 경우 함수 외부의 위치 매개 변수 는 변경하지 않는 한 스크립트에 전달되는 명령 행 인수 입니다.

이를 변경하는 하나의 일반적인 방법은 함께 shift제를 적하하고 감소 의해 왼쪽으로 각 위치 파라미터를 이동 내장, $#1 :

#!/bin/sh

while [ "$#"  -ne 0 ]; do
    printf '%d argument(s) remaining.\nGot "%s".\n\n' "$#" "$1"
    shift
done
$ ./do-shift foo bar baz      # I named the script do-shift.
3 argument(s) remaining.
Got "foo".

2 argument(s) remaining.
Got "bar".

1 argument(s) remaining.
Got "baz".

set내장 기능 으로 변경할 수도 있습니다 .

#!/bin/sh

printf '%d args: %s\n' "$#" "$*"
set foo bar baz
printf '%d args: %s\n' "$#" "$*"
$ ./set-args a b c d e      # I named the script set-args.
5 args: a b c d e
3 args: foo bar baz

1
요청을 넘어서지 만 원래 질문자와 다른 사람의 학습 의도에 반응 한 교육적 대답에 대한 찬사!
Ricardo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.