我在名为 instance 的文件中有一个脚本:
echo "hello world"
echo ${1}
Run Code Online (Sandbox Code Playgroud)
当我使用以下命令运行此脚本时:
./instance solfish
Run Code Online (Sandbox Code Playgroud)
我得到这个输出:
hello world
solfish
Run Code Online (Sandbox Code Playgroud)
但是当我运行时:
echo $#
Run Code Online (Sandbox Code Playgroud)
它说“0”。为什么?我不明白什么$#意思。
请解释一下。
hee*_*ayl 90
$#是一个特殊变量 in bash,它扩展到参数(位置参数)的数量,即$1, $2 ...传递给有问题的脚本或在参数直接传递给 shell 的情况下的 shell,例如 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
Run Code Online (Sandbox Code Playgroud)
请注意,bash -c在从 0 开始的命令之后接受参数($0;从技术上讲,这只是bash让您设置的方式$0,而不是真正的参数),因此_在此处仅用作占位符;实际参数是x( $1)、y( $2) 和z( $3)。
同样,在您的脚本中(假设script.sh),如果您有:
#!/usr/bin/env bash
echo "$#"
Run Code Online (Sandbox Code Playgroud)
然后当你这样做时:
./script.sh foo bar
Run Code Online (Sandbox Code Playgroud)
脚本将输出 2;同样地,
./script.sh foo
Run Code Online (Sandbox Code Playgroud)
将输出 1。
Pil*_*ot6 17
echo $# 输出脚本的位置参数的数量。
你没有,所以它输出 0。
echo $# 在脚本内部很有用,而不是作为单独的命令。
如果您运行带有一些参数的脚本,例如
./instance par1 par2
Run Code Online (Sandbox Code Playgroud)
将echo $#放入该脚本将输出2。
Win*_*nix 15
$#通常用于 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
Run Code Online (Sandbox Code Playgroud)
总结$#报告传递给脚本的参数数量。在您的情况下,您没有传递任何参数,报告的结果是0.
#Bash 中的其他用途在#通常在bash用于计数出现的次数或可变的长度。
要查找字符串的长度:
myvar="some string"; echo ${#myvar}
Run Code Online (Sandbox Code Playgroud)
返回: 11
要查找数组元素的数量:
myArr=(A B C); echo ${#myArr[@]}
Run Code Online (Sandbox Code Playgroud)
返回: 3
要查找第一个数组元素的长度:
myArr=(A B C); echo ${#myArr[0]}
Run Code Online (Sandbox Code Playgroud)
返回:(, 01的长度A是第一个元素,因为数组使用从零开始的索引/下标)。
Eli*_*gan 11
$# 是参数的数量,但请记住它在函数中会有所不同。$#是传递给脚本、shell或 shell 函数的位置参数的数量。这是因为,当 shell 函数运行时,位置参数会临时替换为函数的参数。这让函数接受并使用它们自己的位置参数。
3无论有多少参数传递给脚本本身,该脚本始终打印,因为"$#"在函数中f扩展为传递给函数的参数数量:
#!/bin/sh
f() {
echo "$#"
}
f a b c
Run Code Online (Sandbox Code Playgroud)
这很重要,因为这意味着如果您不熟悉位置参数在 shell 函数中的工作方式,则这样的代码不会像您预期的那样工作:
#!/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...
Run Code Online (Sandbox Code Playgroud)
在check_args,$#扩展为传递给函数本身的参数数量,在该脚本中始终为 0。
如果你想在 shell 函数中使用这样的功能,你必须写这样的东西:
#!/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 "$#"
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为在函数之外$#扩展并作为其位置参数之一传递给函数。在函数内部,扩展到传递给 shell 函数的第一个位置参数,而不是它所属的脚本。$1
因此,像$#,特殊参数$1,$2等等,以及$@和$*,也涉及到传递给函数的参数,当他们在功能被扩展。但是,$0也不能更改的功能,它的名称是为什么我仍然能够用它来生产高质量的错误消息。
$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3
Run Code Online (Sandbox Code Playgroud)
类似地,如果您在另一个函数中定义一个函数,则您正在使用传递给执行扩展的最内部函数的位置参数:
#!/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
Run Code Online (Sandbox Code Playgroud)
我调用了这个脚本nested并且(在运行之后chmod +x nested)我运行了它:
$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments
Run Code Online (Sandbox Code Playgroud)
是的我知道。“1 个参数”是一个复数错误。
如果您正在编写脚本,则函数外部的位置参数将是传递给脚本的命令行参数,除非您对其进行了更改。
改变它们的一种常见方法是使用shift内置函数,它将每个位置参数向左移动一个,删除第一个并减少$#1:
#!/bin/sh
while [ "$#" -ne 0 ]; do
printf '%d argument(s) remaining.\nGot "%s".\n\n' "$#" "$1"
shift
done
Run Code Online (Sandbox Code Playgroud)
$ ./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".
Run Code Online (Sandbox Code Playgroud)
它们也可以使用set内置函数进行更改:
#!/bin/sh
printf '%d args: %s\n' "$#" "$*"
set foo bar baz
printf '%d args: %s\n' "$#" "$*"
Run Code Online (Sandbox Code Playgroud)
$ ./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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
73475 次 |
| 最近记录: |