Bash 中的 $ 符号的作用是参数替换,将参数名替换为参数所代表的值。对于 $ 来说,大括号是可选的,即 $A 和 ${A} 代表同一个参数。
${ } 带冒号的有下面几种表达式:
${parameter:-word}
如果 parameter 为 null 或者未设置,整个参数替换表达式值为 word (注意:这里是整个参数值替换,而不是参数 parameter)
${parameter:=word}
如果 parameter 为 null 或者未设置,整个参数替换表达式值为 word,并且 parameter 参数设置为 word。
${parameter:?word}
如果 parameter 为 null 或者未设置,则打印出错误信息。否则,整个参数替换表达式值为 $parameter
${parameter:+word}
如果 parameter 不为 null 或者未设置,则整个参数替换表达式值为 word
${parameter:offset}
${parameter:offset:length}
parameter 的值的子字符串
可以理解下面几个例子:
${} 带 ! 有下面几种表达式:
${!prefix*}
${!prefix@}
将带有前缀为 prefix 的参数名打印出来
${!name[@]}
${!name[*]}
这个是针对 name 数组的,打印出来 name 数组有哪些下标
可以理解下下面这几个例子:
${ } 带正则匹配的几种表达式:
${parameter#word}
${parameter##word}
从头开始扫描 word,将匹配 word 正则表达式的字符过滤掉
# 为最短匹配,## 为最长匹配
${parameter%word}
${parameter%%word}
从尾开始扫描 word,将匹配 word 正则表达式的字符过滤掉
% 为最短匹配,%%为最长匹配
可以理解下面这几个例子:
${parameter/pattern/string}
${parameter//pattern/string}
将 parameter 对应值的 pattern 字符串替换成为 string 字符串
/ 表示只替换一次
// 表示全部替换
可以;理解下面这几个例子
下面介绍 $( ) 还有 ${ } 还有 ${{ }} 的区别与联系
在 bash shell 中, $( ) 与 ` `(反引号)都是用来做命令替换用(command substitution)的。
所谓的命令替换与我们第五章学过的变量替换差不多,都是用来重组命令行: 完成反引号里的命令行,然后将其结果替换出来,再重组命令行。
例如:
echo the last Sunday is $(date -d "last Sunday" +%Y-%m-%d)
如此,便可方便得到上一星期天的日期了...
在操作上,用 $( ) 或 ` ` 都无所谓,只是建议用 $( ),理由:
1、 ` ` 很容易与 ‘ ’ (单引号) 搞混乱,尤其对初学者来说。
2、 在多层次的复合替换中, ` ` 须要额外的跳脱 ( \` )处理,而 $( ) 则比较直观,例如:
command1 `command2 `command3``
这是错的。
原本的意图是要在 command2 `command3` 先将 command3 替换出来给 command2 处理,然后再将结果传给 command1 `command2...` 来处理。
然而,真正的结果在命令行中却是分成了 `command2` 与 ` ` 两段。
正确的输入应该如下:
command1 `command2 \` command3\` `
要不然,换成 $() 就没问题了:
comand1 $(command2 $(command3))
只要喜欢,做多少层的替换都没有问题
不过,` ` 基本上可用在全部的 Unix Shell 中,若写成 shell script,其移植性比较高。
而 $( ) 并不一定每种 shell 都能使用,但在 bash 中是绝对没问题的。
接下来,再看看 ${ } 它其实就是用来作变量替换的
一般情况下,$var 与 ${var} 并没有不一样,但是用 ${ } 会比较精确的界定变量名称的范围,比如说:
A=B
echo $AB
原本是希望将 $A 的结果替换出来,然后再补一个 B 字母于其后,但在命令行上,真正的结果却是只会替换名称为 AB 的值出来
若使用 ${ } 就没有问题
echo ${A}B
BB
不过 ${ } 的功能远非如此,如下:
假設我們定義了一個變量為:
file=/dir1/dir2/dir3/my.file.txt
我們可以用 ${ } 分別替換獲得不同的值:
${file#*/}:拿掉第一條 / 及其左邊的字串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最後一條 / 及其左邊的字串:my.file.txt
${file#*.}:拿掉第一個 . 及其左邊的字串:file.txt
${file##*.}:拿掉最後一個 . 及其左邊的字串:txt
${file%/*}:拿掉最後條 / 及其右邊的字串:/dir1/dir2/dir3
${file%%/*}:拿掉第一條 / 及其右邊的字串:(空值)
${file%.*}:拿掉最後一個 . 及其右邊的字串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一個 . 及其右邊的字串:/dir1/dir2/dir3/my
記憶的方法為:
- # 是去掉左邊(在鑑盤上 # 在 $ 之左邊)
% 是去掉右邊(在鑑盤上 % 在 $ 之右邊)
單一符號是最小匹配﹔兩個符號是最大匹配。
PS:参考:点击打开链接