1. 4问
hard quote:''(单引号),凡在hard quote中的所有meta均被关闭。
soft quote:""(双引号),放在软引用中大部分的meta都会被关闭,只有少部分如$保留;
escape: \(反斜线),只有紧跟在escape(逃脱字符)之后的单一meta才被关闭;
meta:对于shell来说,具有特定功能的特殊保留字符,部分如下:
1)>: 重定向stdout;
2)<: 重定向stdin;
3)&: 重定向file description,或将命令置于背景执行;
4)(): 将其内的命令置于nested subshell执行或用于运算或命令替换;
5){}: 将其内的命令置于non-named function中执行,或用在变量替换的界定范围;
6); 在前一个命令结束时,而忽略其返回值,继续执行下一个命令;
7)!:执行history列表中的命令。
例子:
$A=B C
$echo " '$A' "
'B C '
原因是单引号在双引号下被去meta,因此会解析$A,然后再加上单引号。
shell会依据IFS(Internal Field Seperator)将command line所输入的文字拆解为"字段(word)".然后再针对特殊字符(meta)先作处理,最后重组整行command line
2. 5问
设定变量遵守的规则:
1)等号左右两边不能使用分隔符(IFS),避免使用shell的保留字符(meta charactor);
2)变量名称不能使用$符号;
3)变量名称的第一个字符不能是数字;
4)变量名称长度不能超过256个字母;
5)变量大小写敏感;
取消变量:unset,变量取消后,是将整个变量拿掉。
3. 6问
fork:默认,在subshell里执行,执行结果不影响parentshell;
source:让脚本在同一个shell里执行,脚本执行完后该shell进程不终止;
exec:让脚本在同一个shell里执行,脚本执行完后该shell进程结束。
进程(process)概念:
我们所执行的任何程序,都是由父进程(parent process)所产生出来的一个子进程,子进程结束后,将返回到父进程去,这个过程为fork;环境变量是那些会传给子进程的变量,只能从父进程到进程单向继承。
执行一个shell script时,其实是先产生一个sub-shell的子进程,然后sub-shell再去产生命令行的子进程。
exec与source/fork的最大差异是原有进程是否终止。
4. 7问
()与{}使用区别:
如果所作的修改是临时的,且不想影响原有或以后的设定,就使用nested sub-shell,否则用non-named command group
5. 8问
$( ) 与``完成符号里的命令行,然后将其结果替换出来,再重组命令行;
${}会比较精确的界定变量名称:$AB ${A}B,另外有些特殊用法(模式截取,数组)
$(( ))他是用来作整数运算的,可用于进制转换$((16#fffff))。(())可重定义变量值或作testing
${}的特异功能:
如:file=/dir1/dir2/dir3/my.file.txt
1)$(file#*/) 拿掉第一条“/”及其左边的字符串,即得dir1/dir2/dir3/my.file.txt;
2)$(file##*/)拿掉最后一条"/"及其左边的字符串;即得my.file.txt;
3)$(file#*.)拿掉第一个"."及其左边的字符串;即得:file.txt;
4)$(file##*/)拿掉最后一条.及其左边的字符串;即得:txt
5)$(file%/*)拿掉最后条"/"及其右边的字符串;即得:/dir1/dir2/dir3
6)$(file%%/*)拿掉第一条"/"及其右边的字符串;即得:空值
记忆的方法:# 是去掉左边(#在$之左边),%是去掉右边(在键盘上的%在$之右边)
单一符号是最小匹配(第一个);两个符号是最大匹配(最后一个)或者看"*"的位置就可以知道删除哪个方向的
8)${file:0:5} 提取最左边的5个字节
9)${file:5:5} 提取第五个字节右边的连续五个字节;
10)${file/dir /path}将第一个dir替换成path;
11)${file//dir /path}将全部dir替换为path;
12)${file-text}如果$file没有设定,则使用text作为回传值;
13)${file:-text}如果$file没有设定或为空值,则使用text作为回传值;
14)${file+text}如果$file设为空值或者非控制,都使用text作为回传值;
15)${file:+text}如果$file为非空值,则使用text作为回传值;
16)${file=text}如果$file没设定,则text作为回传值,同时$file赋值为text;
17)${file:=text}如果$file没设定或为空值,则使用text作为回传值,同时将$file赋值为text;
18)${file?text}如果$file没设定,则将text输出至STDERR
19)${file:?text}如果$file没设定或为空值,则将text输出至STDERR;
一般而言:与null有关,若不带:的话,null不受影响;否则受影响
20)${#var}计算出变量值的长度
21)数组
定义方法 A=(xx x xxx xxxx),bash的数组替换方法:
${A[@]} 或${A} 可以得到数组的全部元素
${A[0]} 可以得到数组的第一个元素;
${#A[@]}或${#A}可得到组数;
${#A[0]} 可以得到数组的第一个元素的长度;
A[2]=X 将第三个元素重新定义。
22)$(())用作整数运算,还可以对不同进制做运算。输出的结果均为十进制。
8. 9问
$# 参数总数量
$@ 除$0以外所有参数
$* 除$0以外所有参数
$0 脚本名称(路径)本身
在funtion内 $0依然是脚本本身,但$1...是函数本身的参数。
$10等效于${1}0
shift可以取消positional parameter中最左边的参数($0 不受影响)
其默认值为1,即shift取消$1,而原本$2变成$1...
测试shell script是否有读进参数:[$#=0]
$@和$*的区别:
两者只有在soft quote中才有差异;
9. 10问
shell跑完一个command或function结束时会传回父进程一个值;
在script中用exit rv来指定,如没有则以结束时最后一道命令rv为值。
在function,用return rv来取代exit rv;
返回值中0为真,非0为假;
test专门测试返回值:return value,命令格式:
test expression or [ expression ]([ ]之间是有空格的)
支持的测试对象有三种:
string:字符串,也就是纯文字;如:["$A"=123]
integer:整数(0或正整数,不含负数或小数点),如:["$A" -eq 123]
file:文件测试,如:[-e "$A"];
test允许多重覆合测试:
expressional -a expressional2 :当两者都为true时才送出true;
expressional -o expressional :只有两者都为false,才送出false;
10. 11问
在shell程序中,最常用到的FD(file descriptor):
0:Standard Input (STDIN)
1:Standard Output(STDOUT)
2:Standard Error Output(STDERR)
1>改变stdout的数据输出信道
2>改变stderr的数据输出信道
0<改变stdin的数据输入的信道
》追加输出到对应的地方
标准定向合并:
2>&1就是将stderr并入stdout作输出;
1>&2将stdout并入stderr作输出
/dev/null 将可以吞掉定向给它的信息
为系统添加禁止覆盖文件的限制:set -o noclobber;取消:set +o noclobber;在限制的情况下仍然想临时覆盖目标文件:在>后面再加个"|"
管道命令:将上一个命令的stdout接到下一个命令的stdin去,而stderr不会接进下一命令;可以把stderr合入到标准输出stdout,[cmd1 2>&1|cmd2...]
多个管道命令中需要将中间一个命令的stdout输入到一个文件保留,可以使用tee命令,tee命令是在不影响原本的I/O的情况下,将stdout复制一份到档案去,即:
cmd1 | cmd2 | tee file | cmd3
cat <> file 从stdin中输入数据定向到 file
cat < file >> file 从file中读取第一个行写入到file中的第二行中,不断的循环操作。
11. 13问
until在条件判断为false则进入循环,否则结束。
break后面可以指定一个数值n,则是"从里往外"打断第n个循环,默认是break 1;
同理,continue后面也可以指定一个数值n,以决定继续哪一层(从里往外计算)的循环,默认值为 continue 1