shell中有许多奇特的语法:
比如有以下一段脚本;
#!/bin/sh files=`find -name *.conifg` for i in $files do name=${i#*/} dir=${name%/*} done
name和dir都代表什么呢?
假如
i=this/is/a/path.config
那么
name=is/a/path.config
dir=this/is/a 错误:应该是is/a
也就是说%/*代表取从头到最后一个slash之前的所有内容
#*/代表去取从第一个slash之后的所有内容
为了更好的理解,我们看一下具体的文档,可参考Advanced Bash-Scripting Guide一书:
${string#substring}Strip shortest match of $substring from front of $string
${string%substring}Strip shortest match of $substring from back of $string
也就是说
#代表删除从前往后最小匹配的内容
%代表删除从后往前最小匹配的内容
name=${i#*/} i:字符串this/is/a/path.config #: 删除字符串开头到第一个匹配的位置的内容 */:匹配的位置满足(任意多个字符+/)
这段代码的含义就是
找到第一个满足(任意多个字符+/)字符串 的位置,this/is/a/path.config
删除前面的内容,/is/a/path.config
剩余的字符串赋值给name
dir=${name%/*} i:字符串/is/a/path.config %: 删除字符串结尾到第一个匹配的位置的内容 */:匹配的位置满足(任意多个字符+/)
为了完整起见,我这里再用一些例子加以说明 ${ } 的一些特异功能:
假设我们定义了一个变量为:
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
记忆的方法为:
# 是去掉左边(在鉴盘上 # 在 $ 之左边)
% 是去掉右边(在鉴盘上 % 在 $ 之右边)
单一符号是最小匹配﹔两个符号是最大匹配。
${file:0:5}:提取最左边的 5 个字节:/dir1
${file:5:5}:提取第 5 个字节右边的连续 5 个字节:/dir2
我们也可以对变量值里的字符串作替换:
${file/dir/path}:将第一个 dir 提换为 path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部 dir 提换为 path:/path1/path2/path3/my