1 数组构造
基本形式是:{x..y[..incr]}
,x、y可以同时是整数或者单个字母,incr是一个可选项,表示增量,是一个整数。
当x、y是整数时,这个表达式扩展为包括x、y在内的所有数。整数可以前缀0,表示打印相同长度的0前缀整数。
当x、y是字母时,这个表达式扩展为包括x、y在内的所有字母(按字典序)。
当使用incr时,incr表示了每个项之间的差,默认是1。
echo {0..10}
打印整数0到10。
$ echo {0..10}
0 1 2 3 4 5 6 7 8 9 10
echo {10..0}
打印同样的数,不过是反向。
$ echo {0..10}
10 9 8 7 6 5 4 3 2 1
echo {10..0..2}
间隔打印整数,每隔一个打印一个,从10开始,一直退到0。
$ echo {10..0..2}
10 8 6 4 2 0
echo {z..a..2}
间隔打印字母,每隔一个打印一个,从z到a。
$ echo {z..a..2}
z x v t r p n l j h f d b
echo {a..c}{a..c}
打印两个字母的组合,从aa到cc。
$ echo {a..c}{a..c}
aa ab ac ba bb bc ca cb cc
在Bash中,你可以这样来构造数组:
$ letter_combos=({a..z}{a..z})
letter_combos指向一个包括整个字母表中字母组合的数组。
你也可以这样:
$ dec2bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
dec2bin包括了所有8比特的二进制数,00000000、00000001、00000010等等,直到11111111。可以用这个数组来构造一个8比特十进制-二进制转换器。比如说你想知道25的二进制是多少,可以这么做:
$ echo ${dec2bin[25]}
00011001
2 参数扩展
这里将$和{}组合使用。
上面的dec2bin其实就涉及了参数扩展,我们来看个简单的:
$ month=("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")
$ echo ${month[3]}
Apr
其中month是一个数组,数组中第3项(从0开始)是Apr,于是${month[3]}
在扩展后就成了Apr。注意这里不能省略{},否则输出Jan[3],因为要将month[3]看成一个整体。
你也可以用参数扩展来操作变量,比如说,删除尾部的字符串:
$ a="Too longgg"
$ echo ${a%gg}
Too long
拆开来讲:
-
${...}
告诉shell要扩展这其中的内容, -
a
是要处理的变量, -
%
告诉shell你想要从变量的尾部删除字符串, - 而
gg
是要删除的字符串。
这个用法在转换文件格式时很方便。
ImageMagick是一系列操作和修改图像的命令行工具。其中最有用的工具是convert
。在其最简单的形式下,convert
可以复制并转换图像的格式。
下面的命令将一个名为image.jpg的JPEG格式图片复制并转换成名为image.png的PNG格式图片:
$ convert image.jpg image.png
利用参数扩展,你可以用以下命令达到相同效果:
$ i=image.jpg
$ convert $i ${i%jpg}png
你所做的就是从变量i中删除后缀jpg,然后再加上后缀png。
所以当你有大批量的JPEG图片需要转换时,就很方便了:
$ for i in *.jpg; do convert $i ${i%jpg}png; done
除了删除尾部字符串,还有其他操作形式:
-
${parameter:-word}
如果parameter未被设置或为空,就带入word;否则带入parameter的值。 -
${parameter:=word}
如果parameter未被设置或为空,就带入word且parameter设置为word;否则带入parameter的值。位置参数不能用这种方式赋值。 -
${parameter:?word}
如果parameter未被设置或为空,打印错误word并退出shell,省略word会打印错误:parameter null or not set;否则带入parameter的值。 -
${parameter:+word}
如果parameter未被设置或为空,就带入空,否则带入parameter的值。
注意:上面word可以是一个变量,使用$word
的形式引用其值 -
${parameter:offset}
截取parameter中offset开始的字符串。 -
${parameter:offset:length}
截取parameter中offset开始长为length的字符串。
注意:上面的offset和length必须为整数。offset和length可以是变量,使用$offset
、$length
引用其值 -
${#parameter}
表示字符串变量的长度;如果parameter是*或@,则扩展为位置参数的个数;如果parameter是数组(以month[@]
形式出现),则表示数组的长度。 -
${parameter#pattern}
把字符串变量前缀与模式进行最小匹配,并删除匹配到的部分。 -
${parameter##pattern}
把字符串变量前缀与模式进行最大匹配,并删除匹配到的部分。 -
${parameter%pattern}
把字符串变量后缀与模式进行最小匹配,并删除匹配到的部分。 -
${parameter%%pattern}
把字符串变量后缀与模式进行最大匹配,并删除匹配到的部分。 -
${parameter/pattern/string}
使用string替换pattern的最大匹配部分。如果pattern以/开头则进行全部替换,否则只替换第一个匹配的位置;如果pattern以#开头,则匹配变量前缀;如果以%开头,则匹配变量后缀。
注意:上面的pattern可以是变量,使用$pattern
引用其值;如果parameter是*、@或数组(以month[@]
形式出现),则对其中每一个元素都进行匹配操作。
3 组合输出
使用{ ... }来把多个命令的输入组合。比如有个命令:
$ echo "I found all these PNGs:"; find . -iname "*.png"; echo "Within this bunch of files:"; ls > PNGs.txt
最终输出到PNGs.txt的只有最后一个ls
的输出。
$ { echo "I found all these PNGs:"; find . -iname "*.png"; echo "Within this bunch of files:"; ls; } > PNGs.txt
这样生成的PNGs.txt会包含所有输出:第一行是“I found all these PNGs:”,然后是一组用find
命令找到的PNG文件名,然后是一行“Within this bunch of files:”,最后是当前目录下所有文件和目录的列表。
注意{}内部的命令前后需要有一个空格,而且命令需要以分号结尾(在脚本中可以是换行)。
4 参考
- All About {Curly Braces} In Bash
- bash(1) - Linux man page