
인스턴스라는 파일에 스크립트가 있습니다.
echo "hello world"
echo ${1}
그리고 다음을 사용하여 이 스크립트를 실행할 때:
./instance solfish
나는 다음과 같은 결과를 얻습니다.
hello world
solfish
하지만 내가 실행할 때 :
echo $#
"0"이라고 적혀있습니다. 왜? 무슨 뜻인지 이해가 안 돼요 $#
.
설명해주세요.
답변1
$#
bash
는 인수(위치 매개변수)의 수만큼 확장되는 의 특수 변수입니다 . 즉 $1, $2 ...
, 문제의 스크립트에 전달되거나 인수가 셸에 직접 전달되는 경우 셸에 전달됩니다(예: in ) bash -c '...' ....
.
argc
이는 C 와 유사합니다 .
아마도 이것은 다음과 같이 명확해질 것입니다.
$ bash -c 'echo $#'
0
$ bash -c 'echo $#' _ x
1
$ bash -c 'echo $#' _ x y
2
$ bash -c 'echo $#' _ x y z
3
는 bash -c
0부터 시작하는 명령 다음에 인수를 취하므로( 기술적으로는 실제로 인수가 아닌 설정을 허용하는 방법일 $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이 출력됩니다.
답변2
echo $#
스크립트의 위치 매개변수 수를 출력합니다.
아무것도 없으므로 0을 출력합니다.
echo $#
별도의 명령이 아닌 스크립트 내부에서 유용합니다.
다음과 같은 일부 매개변수를 사용하여 스크립트를 실행하면
./instance par1 par2
echo $#
스크립트에 배치하면 2가 출력됩니다 .
답변3
$#
일반적으로 bash 스크립트에서 매개변수가 전달되었는지 확인하는 데 사용됩니다. 일반적으로 스크립트 시작 부분에서 매개변수를 확인합니다.
예를 들어, 오늘 작업한 스크립트의 일부는 다음과 같습니다.
if [[ $# -ne 1 ]]; then
echo 'One argument required for the file name, e.g. "Backup-2017-07-25"'
echo '.tar will automatically be added as a file extension'
exit 1
fi
보고서를 요약하면 $#
스크립트에 전달된 매개변수 수를 알 수 있습니다. 귀하의 경우 매개변수를 전달하지 않았으며 보고된 결과는 입니다 0
.
#
Bash의 다른 용도
이는 #
bash에서 변수의 발생 횟수나 길이를 계산하는 데 자주 사용됩니다.
문자열의 길이를 찾으려면:
myvar="some string"; echo ${#myvar}
보고:11
배열 요소 수를 찾으려면 다음을 수행하십시오.
myArr=(A B C); echo ${#myArr[@]}
보고:3
첫 번째 배열 요소의 길이를 찾으려면 다음을 수행하십시오.
myArr=(A B C); echo ${#myArr[0]}
반환: 1
(배열은 0부터 시작하는 인덱스/첨자를 사용하므로 길이가 A
0인 첫 번째 요소입니다.)
답변4
$#
는 인수의 개수이지만 함수에서는 다를 것이라는 점을 기억하세요.
$#
스크립트, 쉘에 전달된 위치 매개변수의 수입니다.또는 쉘 기능. 이는 쉘 기능이 실행되는 동안위치 매개변수는 일시적으로 함수에 대한 인수로 대체됩니다.. 이를 통해 함수는 자신의 위치 매개변수를 받아들이고 사용할 수 있습니다.
이 스크립트는 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...
에서는 함수 자체에 전달된 인수 수로 확장됩니다. 해당 스크립트에서는 항상 0입니다 check_args
.$#
쉘 함수에서 그러한 기능을 원한다면 대신 다음과 같이 작성해야 합니다:
#!/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