Shell 传递参数

$0..$9、$#、$@ 与 $* 的区别、shift、参数校验。

Beginner
Key Points$@ 保留每个参数的原样(推荐加引号),$* 会拼成一个字符串;参数个数用 $#。

位置参数

Bash
#!/bin/bash
echo "script: $0"
echo "first : $1"
echo "second: $2"
echo "count : $#"
Bash
cat > args.sh <<'EOF'
#!/bin/bash
echo "script: $0"
echo "first : $1"
echo "second: $2"
echo "count : $#"
EOF
bash args.sh alpha beta
Output
script: args.sh
first : alpha
second: beta
count : 2
VariableMeaning
$0Script name
$1 … $9Positional parameters
${10}Tenth and beyond need braces
$#Number of arguments
$@All args as separate words
$*All args joined into one string
$$PID of the current shell
$?Exit code of the last command

$@ 与 $*

Bash
#!/bin/bash
echo "with @:"
for a in "$@"; do echo "  [$a]"; done
echo "with *:"
for a in "$*"; do echo "  [$a]"; done
Bash
cat > atstar.sh <<'EOF'
#!/bin/bash
echo "with @:"
for a in "$@"; do echo "  [$a]"; done
echo "with *:"
for a in "$*"; do echo "  [$a]"; done
EOF
bash atstar.sh "a b" c
Output
with @:
  [a b]
  [c]
with *:
  [a b c]

The difference shows inside quotes: "$@" expands to two words (a b, c), while "$*" collapses into one (a b c). Always forward arguments with "$@".

shift

Bash
#!/bin/bash
echo "before: $# args, first=$1"
shift
echo "after : $# args, first=$1"
Bash
cat > shift.sh <<'EOF'
#!/bin/bash
echo "before: $# args, first=$1"
shift
echo "after : $# args, first=$1"
EOF
bash shift.sh one two three
Output
before: 3 args, first=one
after : 2 args, first=two

参数校验

Bash
#!/bin/bash
set -euo pipefail
if [ $# -lt 1 ]; then
    echo "usage: $0 <name>" >&2
    exit 2
fi
echo "hello, $1"
Bash
cat > check.sh <<'EOF'
#!/bin/bash
set -euo pipefail
if [ $# -lt 1 ]; then
    echo "usage: $0 <name>" >&2
    exit 2
fi
echo "hello, $1"
EOF
bash check.sh 2>/dev/null || echo "exit=$?"
bash check.sh Alice
Output
exit=2
hello, Alice
${1:?message} is terser: it aborts when the parameter is empty. ${1:-default} supplies a default, ${1:?} makes it mandatory.

Friends & Partners