关于Linux Shell的展开与匹配

花括号展开

在非引号内的内容,如果用花括号包括,而且里面用逗号分隔(至少包含一个逗号,可以是空内容),这样花括号里的内容会被展开成用空格分开的一个列表,花括号前后可以紧随前缀和后缀(前后缀都是可选的)。
例如:
echo {a,b,c}
echo hello,{world,pig}
echo rep{,,,,,}eat
注意花括号展开,前缀不能是$,因为${...}在shell中是变量

波浪号展开

从波浪号~到第一个未被引号包含的斜杠/(如果没有斜杠,则全部算上),作为波浪号前缀。
在波浪号后面的字符串作为一个可能的登录名:如果为空,被展开成该用户的HOME变量,如果HOME变量未设置,则用用户执行shell的主目录替换。如果不为空,则按照该登录名的主目录替换(原文: If this login name is the null string, the tilde is replaced with the value of the  HOME  shell variable. If  HOME  is unset, the home directory of the user executing the shell is substituted instead. Otherwise, the tilde-prefix is replaced with the home directory associated with the specified login name.
例如:
echo ~   # 显示$HOME内容
HOME=/bin && echo ~   # 显示/bin
unset HOME && echo ~   # 显示当前用户主目录
echo ~root  # 显示root用户主目录

波浪号还可以与加减号和数字,产生一个遍历文件夹堆栈的效果(关于文件夹堆栈,参考dirs、pushd、popd几个命令)。
echo ~+  # 显示$PWD
echo ~-  # 显示$OLDPWD
echo ~+2  # 显示dirs中第3个内容,索引基于0
echo ~-3   # 显示dirs中倒数第4个内容,索引基于0
如果无法展开,那就会原样显示,例如dir堆栈中只有1个内容,那么~+1是无法展开的(这时只有~+0有效)。


Shell参数和变量展开

用$符号开始,后面接着变量名或者花括号括起来的变量名,如果是花括号内以叹号开头,那么就是变量名本身。
例如:
echo $PWD    # 显示PWD对应的值
echo ${PWD} # 显示PWD对应的值
echo ${!PWD}   # 显示“PWD”这个变量名,而不是它的值
echo ${!P*}      # 显示所有以P开头的环境变量名
如果一个变量名不存在,就创建它。
echo ${HELLO:=hello}  # 如果HELLO不存在,就用hello给它赋值,否则直接输出$HELLO的值

命令替换

将一些命令执行后,结果替换到该命令语句中,可以用$()和``括住的方法
命令替换是可以嵌套的。
例如:
echo `date`
echo $(date)
echo $(echo `date` |awk '{print $4}')

算术展开

放在$(( ))中的表达式会被计算,其中变量会被求值,例如:
a=1 && b=3 && echo $(($a+$b))
如果是数字,0开头的8进制,0x开头的16进制,其它进制用Base#number的方式
可支持2~64进制,如果进制小于等于36,可以用a-z或A-Z表示10-35,如果进制大于36,则a-z表示10-35,A-Z表示36-61,@表示62,_表示63
例如:
echo $((16#32))  # 16进制的32,输出50
echo $((64#@_))  # 输出4031 = 62 * 64 + 63
用$[]也可以算术展开,但是不要和测试条件[]混淆了
例如:
echo $[1+4]

进程替换

>(LIST)或<(LIST)
LIST是一个命令,它执行时会从一个FIFO或/dev/fd/xxx这样的地方读取(对应>(LIST))或输出(对应<(LIST)),而这个FIFO或/dev/fd/xxx作为外面命令的一个参数。
例如:
echo -e 'haha hehe\nhaha2 hehe2' >a.txt    # 生成了一个a.txt文件,里面有两行
awk '{ print $2 }' <(cat a.txt)   # 先为<(cat a.txt)生成了一个/dev/fd/63,关联到cat a.txt,也就是说cat a.txt的输出都被定向到/dev/fd/63这个文件了,然后外围的命令执行的是awk '{ print $2 }' /dev/fd/63,这样打印的就是hehe和hehe2。

字词分隔

$IFS里面的任何一个字符都可以作为分隔符,平时我们默认的就是回车、空格、tab符号。
(原文: The shell scans the results of parameter expansion, command substitution, and arithmetic expansion that did not occur within double quotes for word splitting.

The shell treats each character of $IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly "'<space><tab><newline>'", the default, then any sequence of IFS characters serves to delimit words. If IFS has a value other than the default, then sequences of the whitespace characters "space" and "Tab" are ignored at the beginning and end of the word, as long as the whitespace character is in the value of IFS (an IFS whitespace character). Any character in IFS that is not IFS whitespace, along with any adjacent IF whitespace characters, delimits a field. A sequence of IFS whitespace characters is also treated as a delimiter. If the value of IFS is null, no word splitting occurs.

Explicit null arguments ("""" or "''") are retained. Unquoted implicit null arguments, resulting from the expansion of parameters that have no values, are removed. If a parameter with no value is expanded within double quotes, a null argument results and is retained.)


文件名展开

进行字词分隔后,如果不指定-f选项,shell会搜索"*","?","[",如果遇到了,就会认为是一个带pattern的word,然后用字典序将符合的所有文件名替换过去,如果没有文件名匹配:1 shell的nullglob选项关闭,则不进行文件名展开,保留word原样;2 shell的nullglob打开,则移除这个word。如果shell的nocaseglob选项打开,则忽略大小写。


当匹配文件名时(这里指不包括文件夹),除非shell的dotglob被设置,否则.或./开头的文件都必须显示指定,例如:

ls *   # 列出当前文件夹中所有不以"."开头的文件

ls .*  # 列出当前文件夹中所有以"."开头的文件

当匹配文件名时,"/"必需显示匹配,例如:

ls ./* 和 ls ./*/*是不同的。

其它情况下,"."和普通字符一样,例如:

*.txt和*txt都可以匹配a.txt


还有一个系统变量GLOBIGNORE,如果一个文件名匹配了一个pattern word,但是它也匹配了GLOBIGNORE,则它会被忽略,不过两个特殊文件一定会被忽略,就是"."和".."。

如果GLOBIGNORE打开,那么dotglob选项也会自动打开,这样会导致当你ls *时,其他以"."开头的文件也会被match,如果想忽略"."开头的文件,可以在GLOBIGNORE里面添加一个".*"的匹配。如果GLOBIGNORE未设定,则dotglob关闭。


参考:

[1] http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值