bash的brace expansion(大括号扩展)功能

前端之家收集整理的这篇文章主要介绍了bash的brace expansion(大括号扩展)功能前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

刚刚在执行find搜索命令时,报错了。。

$ find ./ -maxdepth 1 -type f -name *.trace
find: paths must precede expression: eEEProIfconfig.trace
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

网上查了下,原来是在使用正则搜索多个文件时,正则PATTERN表达式需要加上引号(单引号和双引号都可以)。

$ find ./ -maxdepth 1 -type f -name "*.trace"
./1.trace
./2.trace
./3.trace

其间网上看到这么两条指令:

$find /data/ -type f -name"*.txt" -exec cp {} /tmp \;
$find /var/www/ -name file -exec cp {}{,.bak} \; 递归备份文件

对其中cp指令后面的空白大括号比较疑惑。带着疑问网上搜索了下,得知{}大括号里的内容为find命令找到的结果

@astrotycoon 的《bash之花括号展开(brace expansion)》这篇博文详细介绍了bash中花括号(大括号)的扩展。
其中下图非常有意思,展示了bash shell的扩展顺序:

refer to "Learning the bash shell"


回到花括号扩展的问题上来,

花括号展开的定义(brace expansion)

花括号扩展有时在别的书籍中也被称为大括号扩展,是可以让bash生成任意字符串的一种扩展功能。它与后面会提到的“路径扩展”非常相似,唯一不同的是生成的字符串可以是不存在的路径或者文件
在bash中,花括号扩展在诸多扩展中的优先级最高,因此像类似于echo {a,b}$PATH的语句在完成花括号扩展之后的结果应该为a$PATH和 b$PATH,而对PATH环境变量的扩展需要到后续的“参数和变量扩展”阶段才开始。

花括号扩展的两种格式

第一类格式为

preamble+{string1,string2,...,stringN}+postscript

左右的花括号是必须的,中间的字符串列表分别由逗号隔开,注意逗号前后不能有空格,如果string中有空格,则需要用单引号或者双引号括起来。

bash在实际扩展时,会将preamble和花括号种的所有字符串(按照从左到右的顺序)相连,最后分别加上postscript。

此外,花括号中间至少有一个逗号,否则bash不会认为这是括号扩展,例如echo {money}就只会输出{money},想要输出money,需要改为echo {money,},如下:

$echo {money}
{money}
$echo {money,}
money
$ echo sp{el,il,al}l
spell spill spall
$ echo sp{el,al}l  //al之前有空格,则原样输出
sp{el,al}l

第二类格式为

preamble+{<START>..<END>[..<INCR>]}+postscript

其中<START>..<END>组合而成的表达式术语叫做序列表达式(sequence expression),表示一个特定的范围。当<START>和<END>是数字时,代表的是数字范围;当<START>和<END>是单个字母时,代表的是字符范围(默认LC_ALL字符排序)。<START>和<END>必须同为数字或者字母,否则bash不认为是花括号扩展,而是原样输出

其中的<INCR>是可选的,代表的是区间范围的递增数,它必须是数字;如果不指定<INCR>,那么默认是1或者是-1,具体是1还是-1,要看前面区间范围是递增的还是递减的。例如:

$ echo {0..10..2}
0 2 4 6 8 10

另外,当和是数字时,我们可以通过在数字前面加0来使输出结果的长度保持一致,例如:

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
$ echo {01..10}
01 02 03 04 05 06 07 08 09 10
$ echo {001..10}
001 002 003 004 005 006 007 008 009 010


下面再举几个例子

例子1:

//将find搜索结果来填充空白大括号
$find /data/ -type f -name"*.txt" -exec cp {} /tmp \;
//将/data/目录下的所有.txt文件复制到/tmp/目录下

注意,这条指令最后的 ; 冒号 是必须要有的。

例子2:

$cp filename{,.bak}
//注意花括号边并没有空格,否则就不是扩展了,变成拷贝为{,.bak}文件了。
//这个命令是用来把filename备份成filename.bak,等同于命令 
$cp filename filename.bak

例子3:

$touch file{1,2,3,4}.txt
$ls
file1.txt  file2.txt  file3.txt  file4.txt



Reference:

find命令结合cp的使用

cp filename{,bak},find /var/www/ -name file -exec cp {}{,.bak} ; 递归备份文件,大括号扩展:cp和mv搭配{,}在shell作用,cp 快速备份 bash{} 扩展。

bash之花括号展开(brace expansion)

bash shell 大括号扩展

猜你在找的Bash相关文章