您的位置:首页 > 运维架构 > Shell

shell编程中特殊字符的问题总结

2011-03-19 10:53 288 查看
From:同事的邮件

通配符( * ):

wildcard是由shell处理的, 它只会出现在 command的argument 里——既不用在 command_name里, 也不用在 options 上。当在argument中碰到Wildcard时,shell会将其当作路径或文件名去在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换(路径扩展);否则就将该wildcard作为一个普通字符传递给command,交由command自行处理

例如,若当前目录下有Cha1、Cha2和Des三个文件,而我想用grep在Des中搜索包含字符串Cha的行,于是写出命令如下:
grep Cha* Des ①
当该命令交由shell处理时,首先会将Cha*中的*当作是一个wildcard,于是就会在当前目录中搜索可能的匹配。*作为wildcard而言匹配的是0个或多个的任意字符,于是文件Cha1和Cha2符合匹配要求,shell自行完成了该命令的重组,重组后的命令为:
grep Cha1 Cha2 Des ②
而这才是最终执行的命令的文本形式。所以命令①实际上的动作是试图在文件Cha2和Des中寻找包含Cha1字符串的行。这和期望grep所作的动作是大相径庭的。
可是,如果当前目录下没有可以匹配Cha*的文件或是文件夹(路径),那么shell会因为找不到可能的匹配而放弃*号的代换,将其传递给command处理,重组后的命令如下:
grep Cha* Des ③

Bash在通配(globbing)中解释特殊字符的行为是可以修改的. set -f命令可以禁用通配(globbing),

二 QUOTING(转义):
1我们说了shell就是一个命令解释器,当shell收到回车符时,shell开始解释整个命令行的命令,如参数,变量,常量等等。那么shell把怎样的字符当作变量呢,它又把怎样的字符当作常量呢?这里就不得不提到shell中的两种字符:
(1)literal : 就是普通字符 对shell而言没有什么特殊的意义,比如:AA 123213等
(2)meda : shell的一些元字符,在shell中元字符是保留的有特殊用法的字符

这里先介绍两个最为常用的元字符:
(1)IFS 由空格,Tab或者<Enter>组成,用来分隔字符的字符,shell视它们为命令中一个字符的结束,后面跟的会是另外的命令或者字符,与它们前面的东西没有关联
(2)CR 由<Enter>产生,它的作用就是结束命令行的输入,开始执行shell命令

除了 IFS 与 CR ,常用的 meta 还有:
= : 设定变量。
$ : 作变量或运算替换。
> :重导向 stdout。
< :重导向 stdin。
|:命令管线。
& :重导向 file descriptor ,或将命令置于背境执行。
( ):将其内的命令置于 nested subshell 执行,或用于运算或命令替换。
{ }:将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围。
; :在前一个命令结束时,而忽略其返回值,继续执行下一个命令。
&& :在前一个命令结束时,若返回值为 true,继续执行下一个命令。
|| :在前一个命令结束时,若返回值为 false,继续执行下一个命令。
!:执行 history 列表中的命令

假如我们需要在 command line 中将这些保留字符的功能关闭的话,就需要quoting 处理了。shell中的meta、有时会和command中的meta相同,为了让command中的meta不被shell解析以至于改变,就必须用shell quoting(单引号,双引号,反斜线)来保证其文字不变性。:
* hard quote:' ' (单引号),凡在 hard quote 中的所有 meta 均被关闭。
* soft quote: " " (双引号),在 soft quoe 中大部份 meta 都会被关闭,但某些则保留
* escape : \ (反斜线),只有紧接在 escape (跳脱字符)之后的单一 meta才被关闭。

1. 单引号 ( ' ' )
howard@0[script]$ grep Susan phonebook
Susan Goldberg 403-212-4921
Susan Topple 212-234-2343

如果我们想查找的是Susan Goldberg,不能直接使用grep Susan Goldberg phonebook命令,grep会把Goldberg和phonebook当作需要搜索的文件
howard@0[script]$ grep 'Susan Gold' phonebook
Susan Goldberg 403-212-4921
当shell碰到第一个单引号时,它忽略掉其后直到右引号的所有特殊字符

2. 双引号 ( " " )
双引号作用与单引号类似,区别在于它没有那么严格。单引号告诉shell忽略所有特殊字符,而双引号只要求忽略大多数,具体说,括在双引号中的四种特殊字符不被忽略:$,\,` ,! (历史命令) ,
howard@0[script]$ x=*
howard@0[script]$ echo $x
hello.sh menus.sh misc.sh phonebook tshift.sh
howard@0[script]$ echo '$x'
$x
howard@0[script]$ echo "$x"
*

3. 反斜杠 backslash-escaped( \ )
反斜杠一般用作转义字符,或称逃脱字符,放在指令前,有取消 aliases 的作用;放在特殊符号前,则该特殊符号的作用消失;放在指令的最末端,表示指令连接下一行

补充一些特殊符号:
3. 反引号(``)
命令替换是指shell能够将一个命令的标准输出插在一个命令行中任何位置。shell中有两种方法作命令替换:把shell命令用反引号或者$(...)结构括起来,其中,$(...)格式受到POSIX标准支持,也利于嵌套。
howard@0[script]$ echo The date and time is `date`
The date and time is 三 6月 15 06:10:35 CST 2005
howard@0[script]$ echo Your current working directory is $(pwd)
Your current working directory is /home/howard/script.

1、{} 大括号:
eg: ls my_{finger,toe}s
这条命令相当于如下两个命令的组合:
ls my_fingers ; ls my_toes
eg: mkdir {userA,userB,userC}-{home,bin,data}
我们得到 userA-home, userA-bin, userA-data, userB-home, userB-bin, userB-data,
userC-home, userC-bin, userC-data,这几个目录
可用于语句块的构造,命令之间可用回车隔开

用法二:参数扩展
${name:-default} 使用一个默认值(一般是空值)来代替那些空的或者没有赋值的变量name;
${name:=default}使用指定值来代替空的或者没有赋值的变量name;
${name:?message}如果变量为空或者未赋值,那么就会显示出错误信息并中止脚本的执行同时返回退出码1。
${#name} 给出name的长度
${name%word} 从name的尾部开始删除与word匹配的最小部分,然后返回剩余部分
${name%%word} 从name的尾部开始删除与word匹配的最长部分,然后返回剩余部分
${name#word} 从name的头部开始删除与word匹配的最小部分,然后返回剩余部分
${name##word} 从name的头部开始删除与word匹配的最长部分,然后返回剩余部分
(注,name为变量名,word为要匹配的字符串)

2、[] 中括号:允许匹配方括号中任何一个单个字符
eg: ls /[eh][to][cm]*
相当于执行 ls /etc 和 ls /home

3、AND列表 statement1 && statement2 && statement3 && ……:只有在前面所有的命令都执行成功的情况下才执行后一条命令

4、OR列表 statement1 || statement2 || statement3 || ……:允许执行一系列命令直到有一条命令
成功为止,其后所有命令将不再被执行

5、** 次方运算:两个星号在运算时代表 "次方" 的意思
eg:let "sus=2**3"
echo "sus = $sus"
# sus = 8

6、$((...))语法:对括号内的表达式求值
eg:
#!/bin/sh
x=0
hile [ "$x" -ne 10 ];do
echo $x
x=$(($x+1))
done
exit 0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: