bash脚本中$@和$*之间的差异[复制]

时间:2021-09-20 00:29:09

This question already has an answer here:

这个问题已经有了答案:

There are 4 bash snippets below. I call them with ./script.sh a b c

下面有4个bash片段。我用。/脚本给他们打电话。sh a b c

for arg in $@; do 
echo "$arg"
done   ## output "a\nb\nc"

for arg in "$@"; do
echo "$arg"
done  ## output "a\nb\nc" -- I don't know why

for arg in $*; do
echo "$arg"
done  ##    output "a\nb\nc"

for arg in "$*"; do
echo "$arg"
done    ## output "abc"

I don't know what is the exact difference between $@ and $*,
and I think "$@" and "$*" should be the same, but they are not. Why?

我不知道$@和$*的确切区别是什么,我认为$@和$*应该是一样的,但它们不是。为什么?

3 个解决方案

#1


20  

If you have a script foo.sh:

如果你有一个脚本foo.sh:

asterisk "$*"
at-sign "$@"

and call it with:

并称之为:

./foo.sh "a a" "b b" "c c"

it's equivalent to:

等价于:

asterisk "a a b b c c"
at-sign "a a" "b b" "c c"

Without the quotes, they're the same:

没有引号,它们是一样的:

asterisk $*
at-sign $@

would be equivalent to:

就相当于:

asterisk "a" "a" "b" "b" "c" "c"
at-sign "a" "a" "b" "b" "c" "c"

#2


6  

Difference between $* and $@ is::

$*与$@之间的差额为:

"$*" All the positional parameters (as a single word) *

“$*”所有位置参数(作为一个词)*

"$@" All the positional parameters (as separate strings)

“$@”所有位置参数(作为单独的字符串)

If you pass three command-line arguments given to a bash script to a C program using ./my_c $@,

如果您将三个命令行参数传递给了一个使用./my_c $@的bash脚本,

you get the result ARG[1] == "par1" ARG[2] == "par2" ARG[3] == "par3"

得到结果ARG[1] = "par1" ARG[2] = "par2" ARG[3] = "par3"

If you pass three command-line arguments given to a bash script to a C program using ./my_c $*,

如果您使用。/my_c $*将给bash脚本的三个命令行参数传递给C程序,

you get the result ARG[1] == "par1 par2 par3"

得到的结果是ARG[1] = "par1 par2 par3"

#3


1  

This matters in shell scripts: for example the script testargs.sh

这在shell脚本中很重要:例如脚本testargs.sh

#! /bin/bash -p

echo $#

for i in $(seq 1 $#)
do
    echo "$i: ${!i}"
done

for val in "$@"; do
    echo "in quote @, $val"
done

for val in "$*"; do
    echo "in quote *, $val"
done

for val in $@; do
    echo "not in quote @, $val"
done

for val in $*; do
    echo "not in quote *, $val"
done

If this script is executed as /tmp/testargs.sh a b c 'd e', the results are:

如果这个脚本执行为/tmp/testargs。a b c 'd e',结果是:

4
1: a
2: b
3: c
4: d e
in quote @, a
in quote @, b
in quote @, c
in quote @, d e
in quote *, a b c d e
not in quote @, a
not in quote @, b
not in quote @, c
not in quote @, d
not in quote @, e
not in quote *, a
not in quote *, b
not in quote *, c
not in quote *, d
not in quote *, e

Thus, if number of arguments are to be preserved, always use "$@" or iterate through each argument using the for i in $(seq 1 $#) loop. Without quotes, both are same.

因此,如果要保留参数的数量,请始终使用“$@”或使用$(seq 1 $#)循环中的for i迭代每个参数。没有引号,两者都是一样的。

#1


20  

If you have a script foo.sh:

如果你有一个脚本foo.sh:

asterisk "$*"
at-sign "$@"

and call it with:

并称之为:

./foo.sh "a a" "b b" "c c"

it's equivalent to:

等价于:

asterisk "a a b b c c"
at-sign "a a" "b b" "c c"

Without the quotes, they're the same:

没有引号,它们是一样的:

asterisk $*
at-sign $@

would be equivalent to:

就相当于:

asterisk "a" "a" "b" "b" "c" "c"
at-sign "a" "a" "b" "b" "c" "c"

#2


6  

Difference between $* and $@ is::

$*与$@之间的差额为:

"$*" All the positional parameters (as a single word) *

“$*”所有位置参数(作为一个词)*

"$@" All the positional parameters (as separate strings)

“$@”所有位置参数(作为单独的字符串)

If you pass three command-line arguments given to a bash script to a C program using ./my_c $@,

如果您将三个命令行参数传递给了一个使用./my_c $@的bash脚本,

you get the result ARG[1] == "par1" ARG[2] == "par2" ARG[3] == "par3"

得到结果ARG[1] = "par1" ARG[2] = "par2" ARG[3] = "par3"

If you pass three command-line arguments given to a bash script to a C program using ./my_c $*,

如果您使用。/my_c $*将给bash脚本的三个命令行参数传递给C程序,

you get the result ARG[1] == "par1 par2 par3"

得到的结果是ARG[1] = "par1 par2 par3"

#3


1  

This matters in shell scripts: for example the script testargs.sh

这在shell脚本中很重要:例如脚本testargs.sh

#! /bin/bash -p

echo $#

for i in $(seq 1 $#)
do
    echo "$i: ${!i}"
done

for val in "$@"; do
    echo "in quote @, $val"
done

for val in "$*"; do
    echo "in quote *, $val"
done

for val in $@; do
    echo "not in quote @, $val"
done

for val in $*; do
    echo "not in quote *, $val"
done

If this script is executed as /tmp/testargs.sh a b c 'd e', the results are:

如果这个脚本执行为/tmp/testargs。a b c 'd e',结果是:

4
1: a
2: b
3: c
4: d e
in quote @, a
in quote @, b
in quote @, c
in quote @, d e
in quote *, a b c d e
not in quote @, a
not in quote @, b
not in quote @, c
not in quote @, d
not in quote @, e
not in quote *, a
not in quote *, b
not in quote *, c
not in quote *, d
not in quote *, e

Thus, if number of arguments are to be preserved, always use "$@" or iterate through each argument using the for i in $(seq 1 $#) loop. Without quotes, both are same.

因此,如果要保留参数的数量,请始终使用“$@”或使用$(seq 1 $#)循环中的for i迭代每个参数。没有引号,两者都是一样的。