主要内容
命令替换$()
命令替换用于在shell中执行指定的命令,并把命令的输出捕获返回给shell。
例如:
1 2 |
[centos7-server ~]# echo $(date) Wed Mar 14 15:57:01 CST 2018 |
上面的例子不太实用。另一个例子是,根据日期动态设置备份文件的名称。
1 2 3 4 |
#!/bin/bash FileName=backup_$(date +%Y%m%d) echo $FileName |
文件名称就是backup_20180314。文件名会根据当前的实际时间作出变更。
命令替换还有其他写法,这种写法主要是兼容旧的shell,例如:
1 2 3 4 |
#!/bin/bash FileName=backup_`date +%Y%m%d` echo $FileName |
不过需要注意的是:命令替换会创建一个新的子shell来执行命令,也就是说,非全局变量将不能被这个子shell使用,除非是export变量。
source命令
source命令的别名叫做点( . )命令。当我们执行一个shell脚本的时候,都是在一个新建的环境中执行的,原来环境中的变量就无法使用。利用source命令,可以使shell脚本执行在旧的环境中,以便使用旧环境中的变量。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#source.sh脚本的内容 #!/bin/sh echo $var #以下内容在shell中进行操作,不在source.sh脚本中 #定义一个变量var konrida@kubuntu-vm:~/shellscript$ var="var in parent shell" #使用普通方式执行shell,因为变量不存在,所以无法打印var的值 konrida@kubuntu-vm:~/shellscript$ ./source.sh #通过source方式执行shell脚本,使脚本在当前环境中执行,所以能打印var变量的值 konrida@kubuntu-vm:~/shellscript$ source ./source.sh var in parent shell #使用点操作符执行脚本,点操作符是source的别名操作符 konrida@kubuntu-vm:~/shellscript$ . ./source.sh var in parent shell |
echo命令
echo命令用于在终端中输出文本,它有一些常用参数:-n 、-e
-n参数用于删除行尾的换行符,但这个选项不具备可移植性
1 |
echo -n "string to output" |
-e选项用于保留转义字符的作用
1 2 3 4 5 |
#不带-e参数的情况下,字符串中的\c会原样输出 echo "hello bash shell\c" #加上-e参数后,\c的作用会被保留,因此,换行符被删除 echo -e "hello bash shell\c" |
printf命令
printf命令只有在新版本的shell中才有的命令,用于代替echo命令。printf命令的好处是可以格式化输出,像c语言中的printf。
1 2 3 4 5 6 |
#输出hello并换行 printf "%s\n" hello #输出Hi There 15 people #因为Hi There中有空格,因此要使用引号使它成为一个单独参数 printf "%s %d\t%s" "Hi There" 15 people |
set命令
set命令在之前的文章中有所提及,它的一个作用是设置shell的选项,以控制shell的行为。它还有一个作用:设置或重新设置位置参数的值。在不使用set的前提下,位置参数的值是无法修改的。
例如:set.sh脚本中有如下代码,单纯打印位置参数的值
1 2 |
#!/bin/sh echo $1 $2 $3 |
在shell中运行该脚本
1 2 |
konrida@kubuntu-vm:~/shellscript$ ./set.sh one two three one two three |
使用set修改位置参数的值
在上面的脚本中添加一行代码后如下:
1 2 3 |
#!/bin/sh set "parameter-one" $2 $3 echo $1 $2 $3 |
然后执行脚本
1 2 |
konrida@kubuntu-vm:~/shellscript$ ./set.sh one two three parameter-one two three |
虽然传递参数的时候第一个参数值是one,但是在脚本里面one已被set重新设置了新的值。因此位置参数$1的值变成了parameter-one。
需要注意的是,如果set设置的参数个数小于传递给脚本的参数个数,那么脚本的参数以set设置的为准,用户传递的参数被作废。
例如:
1 2 3 4 |
#!/bin/sh #set只设置了一个参数 set "parameter-one" echo $1 $2 $3 |
运行脚本观察输出结果:
1 2 |
konrida@kubuntu-vm:~/shellscript$ ./set.sh one two three parameter-one |
虽然我们传递了三个参数给脚本,但是set只设置了一个参数,所以其他的参数都被丢弃了。
再谈双引号
set命令设置的参数以空格为分隔符,例如:set a b c 命令设置了3个参数,值分别是a、b和c。如果使用双引号的话:set “a b c”,则整个字符串作为一个参数。看下面的例子:
1 2 3 4 5 6 7 8 |
konrida@kubuntu-vm:~/shellscript$ date Thu Dec 28 16:37:30 CST 2017 konrida@kubuntu-vm:~/shellscript$ set $(date) konrida@kubuntu-vm:~/shellscript$ echo $2 Dec konrida@kubuntu-vm:~/shellscript$ set "$(date)" konrida@kubuntu-vm:~/shellscript$ echo $1 Thu Dec 28 16:37:48 CST 2017 |
date命令的输出格式是以空格分开的时间值,因此,使用set $(date)
,每一个被空格隔开的值作为一个位置参数,而当使用双引号把date返回的结果括起来后"$(date)"
,set只有一个位置参数。
shift命令
shift命令把所有参数变量左移一个位置,$2变成$1, $3变成$2,$1则被丢弃,$0保持不变。如果调用shift的时候指定了一个值,则所有的参数将左移指定的次数。
例如:
1 2 3 |
#!/bin/sh shift 2 echo $1 $2 $3 $4 |
运行:
1 2 |
konrida@kubuntu-vm:~/shellscript$ ./shift.sh one two three four five three four five |
由于左移了两个位置,参数$2没有了,直接从$3开始,$3变成$1, $5变成$3。
trap命令
trap命令用于指定接收到某个信号后要执行的操作,这个操作是可选的,如果没有指定操作,则使用默认行为处理这个信号,例如SIGINT信号默认退出程序。可以使用trap -l
查看相关的信号列表,使用信号时可以使用完整的信号名称,也可以使用简单的信号名称(去掉SIG前缀)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#!/bin/sh temp_file="/tmp/my_tmp_file_$$" trap "rm -f ${temp_file}" INT #当中断信号到来,删除临时文件 echo creating file ${temp_file} date > ${temp_file} echo "press interrupt (CTRL-C) to interrupt ..." while [ -f ${temp_file} ]; do #只要临时文件存在则一直循环 echo FILE exists sleep 1 #每次循环时睡眠1秒 done echo The file no longer exists trap INT #没有指定要执行的操作,默认退出程序 echo creating file ${temp_file} date > ${temp_file} echo "press interrput (control-C) to interrupt ..." while [ -f ${temp_file} ]; do echo File exists sleep 1 done echo we never get here exit 0 |
如果想还原信号的默认行为,可以像下面这样,三种方法都可以,例如:
1 2 3 |
trap INT trap - INT trap -- INT |
exec命令
exec命令的主要用法是把当前的shell替换为一个不同的程序。
例如:
1 2 3 4 5 6 7 |
#显示当前shell的进程号 konrida@kubuntu-vm:~$ echo $$ 1875 #在当前shell中使用exec执行top程序 #当我们使用q退出top的时候,并没有返回到shell中,而是直接关闭了进程, #因为shell进程已经被top替换了,因此top的进程号是1875 konrida@kubuntu-vm:~$ exec top |
eval命令
eval命令的作用和JavaScript中的eval类似,用于解析字符串中是否有可执行的shell命令,如果是,则 执行该命令。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#定义变量today konrida@kubuntu-vm:~$ today=$(date) konrida@kubuntu-vm:~$ echo $today Fri Dec 29 15:25:18 CST 2017 #使用eval之前,str中的值只是一个字符串 konrida@kubuntu-vm:~$ str='$today' konrida@kubuntu-vm:~$ echo $str $today #使用eval命令,字符串'$today'被解析为一个shell命令并执行, #然后把执行后的值赋给str,最后,str变量拥有了today变量的值 konrida@kubuntu-vm:~$ eval str='$today' konrida@kubuntu-vm:~$ echo $str Fri Dec 29 15:25:18 CST 2017 |
转载请注明:Pure nonsense » shell程序设计(五)常用命令