$@ 与 $* 差在哪?-- Shell十三问<第九问>

要说 $@ 与 $* 之前,需得先从 shell script 的 positional parameter 谈起.我们都已经知道变量(variable)是如何定义及替换的,这个不用再多讲了。

但是,我们还需要知道有些变量是 shell 内定的,且其名称是我们不能随意修改的,其中就有 positional parameter 在内。

在 shell script 中,我们可用 $0, $1, $2, $3 ... 这样的变量分别提取命令行中的如下部份:

script_name parameter1 parameter2 parameter3 .

我们很容易就能猜出 $0 就是代表 shell script 名称(路径)本身,而 $1 就是其后的第一个参数,如此类推.须得留意的是 IFS 的作用,也就是,若 IFS 被 quoting 处理后,那么 positional parameter 也会改变。

如下例:

my.sh p1 "p2 p3" p4

由于在 p2 与 p3 之间的空格键被 soft quote 所关闭了,因此 my.sh 中的 $2 是 "p2 p3",而 $3 则是 p4.

还记得前两章我们提到 fucntion 时,我不是说过它是 script 中的 script 吗?

是的,function 一样可以读取自己的(有别于 script 的) postitional parameter ,惟一例外的是 $0 而已。

举例而言:假设 my.sh 里有一个 fucntion 叫 my_fun , 若在 script 中跑 my_fun fp1 fp2 fp3,那么,function 内的 $0 是 my.sh ,而 $1 则是 fp1 而非 p1 了.

不如写个简单的 my.sh script 看看吧:

#!/bin/bash
my_fun() {
echo '$0 inside function is '$0
echo '$1 inside function is '$1
echo '$2 inside function is '$2
}
echo '$0 outside function is '$0
echo '$1 outside function is '$1
echo '$2 outside function is '$2
my_fun fp1 "fp2 fp3" 然后在 command line 中跑一下 script 就知道了:
chmod +x my.sh
./my.sh p1 "p2 p3"
$0 outside function is ./my.sh
$1 outside function is p1
$2 outside function is p2 p3
$0 inside function is ./my.sh
$1 inside function is fp1
$2 inside function is fp2 fp3

使用 positional parameter 的时候,我们要注意一些陷阱哦:

  • $10 不是替换第 10 个参数,而是替换第一个参数($1)然后再补一个 0 于其后!

    也就是,my.sh one two three four five six seven eigth nine ten 这样的 command line ,my.sh 里的 $10 不是 ten 而是 one0 哦.

要抓到 ten 的话,有两种方法:

  1. 方法一,是使用我们上一章介绍的 ${ } ,也就是用 ${10} 即可。
  2. 方法二,就是 shift 了。

用通俗的说法来说,所谓的 shift 就是取消 positional parameter 中最左边的参数( $0 不受影响)。其默认值为 1 ,也就是 shift 或 shift 1 都是取消 $1 ,而原本的 $2 则变成 $1、$3 变成 $2. 若 shift 3 则是取消前面三个参数,也就是原本的 $4 将变成 $1.

那,亲爱的读者,你说要 shift 掉多少个参数,才可用 $1 取得 ${10} 呢? 当我们对 positional parameter 有了基本概念之后,那再让我们看看其它相关变量吧。

首先是 $# :它可抓出 positional parameter 的数量。以前面的 my.sh p1 "p2 p3" 为例:

由于 p2 与 p3 之间的 IFS 是在 soft quote 中,因此 $# 可得到 2 的值。但如果 p2 与 p3 没有置于 quoting 中话,那 $# 就可得到 3 的值了。

同样的道理在 function 中也是一样的.

因此,我们常在 shell script 里用如下方法测试 script 是否有读进参数:

[ $# = 0 ]
假如为 0 ,那就表示 script 没有参数,否则就是有带参数...
接下来就是 $@ 与 $* :
精确来讲,两者只有在 soft quote 中才有差异,否则,都表示"全部参数"( $0 除外)。
举例来说好了:
若在 command line 上跑 my.sh p1 "p2 p3" p4 的话,
不管是 $@ 还是 $* ,都可得到 p1 p2 p3 p4 就是了。
但是,如果置于 soft quote 中的话:
"$@" 则可得到 "p1" "p2 p3" "p4" 这三个不同的词段(word)﹔
"$*" 则可得到 "p1 p2 p3 p4" 这一整串单一的词段。

我们可修改一下前面的 my.sh ,使之内容如下:

#!/bin/bash
my_fun() {
echo "$#"
}
echo 'the number of parameter in "$@" is '$(my_fun "$@")
echo 'the number of parameter in "$*" is '$(my_fun "$*")
然后再执行 ./my.sh p1 "p2 p3" p4 就知道 $@ 与 $* 差在哪了 .

$@ 与 $* 差在哪?-- Shell十三问<第九问>的更多相关文章

  1. > 与 < 差在哪?-- Shell十三问<第十一问>

    > 与 < 差在哪?-- Shell十三问<第十一问> 谈到 I/O redirection ,不妨先让我们认识一下 File Descriptor (FD) .程序的运算,在 ...

  2. && 与 || 差在哪?-- Shell十三问<第十问>

    && 与 || 差在哪?-- Shell十三问<第十问> 好不容易,进入两位数的章节了... 一路走来,很辛苦吧?也很快乐吧? 在解答本章题目之前,先让我们了解一个概念:r ...

  3. $(( )) 与 $( ) 还有${ } 差在哪?-- Shell十三问<第八问>

    $(( )) 与 \(( ) 还有\){ } 差在哪?-- Shell十三问<第八问> 我们上一章介绍了 ( ) 与 { } 的不同,这次让我们扩展一下,看看更多的变化:$( ) 与 \( ...

  4. ( ) 与 { } 差在哪?-- Shell十三问<第七问>

    ( ) 与 { } 差在哪?-- Shell十三问<第七问> 先说一下,为何要用 ( ) 或 { } 好了. 许多时候,我们在 shell 操作上,需要在一定条件下一次执行多个命令,也就是 ...

  5. exec 跟 source 差在哪?-- Shell十三问<第六问>

    exec 跟 source 差在哪?-- Shell十三问<第六问> 这次先让我们从 CU Shell 版的一个实例贴子来谈起吧: 例中的提问是: cd /etc/aa/bb/cc 可以执 ...

  6. var=value?export前后差在哪?-- Shell十三问<第五问>

    var=value?export前后差在哪?-- Shell十三问<第五问> 这次让我们暂时丢开 command line ,先来了解一下 bash 变量(variable)吧.所谓的 变 ...

  7. " "( 双引号) 与 ' '( 单引号) 差在哪?-- Shell十三问<第四问>

    " "( 双引号) 与 ' '( 单引号) 差在哪?-- Shell十三问<第四问> 经过前面两章的学习,应该很清楚当你在 shell prompt 后面敲打键盘.直到 ...

  8. 别人 echo 、你也 echo ,是问 echo 知多少?-- Shell十三问<第三问>

    别人 echo .你也 echo ,是问 echo 知多少?-- Shell十三问<第三问> 承接上一章所介绍的 command line ,这里我们用 echo 这个命令加以进一步说明. ...

  9. [^ ] 跟 [! ] 差在哪?-- Shell十三问<第十四问>

    [^ ] 跟 [! ] 差在哪?-- Shell十三问<第十四问> 这道题目说穿了, 就是要探讨 Wildcard(通配符)与 Regular Expression(正则表达式)的差别的. ...

  10. shell十三问

    1) 为何叫做 shell ?在介绍 shell 是甚幺东西之前,不妨让我们重新检视使用者与计算机系统的关系:图(FIXME)我们知道计算机的运作不能离开硬件,但使用者却无法直接对硬件作驱动,硬件的驱 ...

随机推荐

  1. Emmet & VSCode

    Emmet & VSCode Emmet - the essential toolkit for web-developers https://emmet.io/ https://emmet. ...

  2. BattleBots

    BattleBots 搏茨大战 https://battlebots.com/ BiteForce https://www.youtube.com/watch?v=06lyUXuQT_Y xgqfrm ...

  3. 小程序 怎么发 beta 版本

    小程序 怎么发 beta 版本 微信 https://developers.weixin.qq.com/miniprogram/dev/devtools/mydev.html 小程序助手 支付宝 ht ...

  4. uniapp vue mixin使用

    这个mixin的翻版,主要用来分离处理列表数据逻辑 我用了覆写模式 创建mixin ListMoreDataMixin // 由于没有超类的限制这里要判断下 function ____checkGet ...

  5. js 脏检测

    参考 基础知识 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  6. IdentityServer4之Authorization Code(授权码)相对更安全

    前言 接着授权模式聊,这次说说Authorization Code(授权码)模式,熟悉的微博接入.微信接入.QQ接入都是这种方式(这里说的是oauth2.0的授权码模式),从用户体验上来看,交互方式和 ...

  7. MySQL 常用命令手册 增删改查大法

    一.数据库操作 创建数据库 语法: CREATE DATABASE database_name; 删除数据库 删除数据库务必谨慎!因为执行删除命令后,所有数据将消失. 语法: DROP DATABAS ...

  8. 2021 年学习 React 的所需要的 JavaScript 基础

    在理想的情况中,您可以先了解所有有关 JavaScript 和 web 开发的知识,然后再深入了解React. 但是,我们没有办法这样,如果等你把所有 JavaScript 的知识都掌握了再去学习 R ...

  9. vue中将分号去掉,将双引号变为单引号的配置

    在项目根目录下创建.prettierrc文件,文件内容如下: { "semi": false, "singleQuote": true } 实现vs code中 ...

  10. 如何用Eggjs从零开始开发一个项目(3)

    上一篇中我们编写了用户注册登录.登录的代码,学习了如何进行用户的认证(JWT),如何安全地存储用的密码(hash).这一篇我们有以下2个任务: 获取token中的数据: 通过model来同步数据库. ...