Day 58 shell脚本命令
1.概念:
Shell 是 linux 中一个重要的层次,它是用户与系统交互作用的界面。在介绍 linux 命令时, shell 都作为命令解释程序出现:它接收用户打入的命令,进行分析,创建子进程实现命令所规定的功能,等子进程终止工作后,发出提示符。这是 shell 最常见的使用方式。 Shell 除了作为命令解释程序以外,还是一种高级程序设计语言, 它有变量,关键字,有各种控制语句,如 if , case , while , for 等语句,有自己的语法结构 。利用 shell 程序设计语言可以编写出功能很强、但 代码简单的程序,特别是它把相关的 linux 命令有机地组合在一起,可大大提高编程的效率,充分利用 linux 系统的开放性能,设计出适合自己要求的命令。 2.简单的脚本: 脚本文件后缀为.sh,创建和打开用vim命令。第一行为#!/bin/bash 后面可将Linux中的命令加上去,最终的结果和在终端输入一致。
下面是一个简单的shell脚本示例:
#!/bin/bash
#This is to show what a example looks like
date
echo "Our first example."
echo #this inserts an empty line in output .
echo "We are currently in the following diractory."
echo
/bin/pwd
echo
echo "This diractory contains following files"
/bin/ls Shell 脚本中用 # 表示注释,相当于 C 语言的 // 注释。但如果 # 位于第一行开头,并且是 #! ( 称为 Shebang)则例外,它表示该脚本使用后面指定的解释器 /bin/sh 解释执行。如果把这个脚本文件加上可执行权限然 后执行 :,执行方式如下: user02@vir:~$ chmod a+x test.sh user02@vir:~$ ./test.sh #方法一 user02@vir:~$ . test.sh #方法二 user02@vir:~$ source test.sh #方法三 更改权限则使用chmod命令。 3.shell语法: 数据类型只有字符串 Shell 变量名通常是以 字母或下划线打头的字母、数字和下划线字符序列,并且大小写字母意义不同 。有两种类型的 Shel l变量:环境变量和临时变量 环境变量: 环境变量可以从父进程传给子进程,因此 Shell 进程的环境变量可以从当前 Shell 进程传给 fork 出来的子进程。用 printenv 命令可以显示当前 Shell 进程的环境变量。 临时变量: 只存在于当前 Shell 进程,用 set 命令可以显示当前 Shell 进程中定义的所有变量 (包括临时变量和环境变 环境变量是任何进程都有的概念,而临时变量是 Shell 特有的概念。在 Shell 中,环境变量和临时变量的定义和用法相似。在 Shell 中定义或赋值一个变量 量) 和函数: user02$ VARNAME=HELLO #定义一个临时变量 user02$ export VARNAME=HELLO #定义一个环境变量 user02$ env | grep VARNAME #env能查到就是环境变量,查不到就是临时变量 user02$ unset VARNAME #取消环境变量 文件名代换: 这些用于匹配的字符称为通配符 (wildcard), 如 : * ? [ ] 具体如下 : * :匹配 0 个或多个任意字符 ? :匹配一个任意字符 [ 若干字符 ] : 匹配方括号中任意一个字符的次出现一次的文件名 命令代换: 由 “ ' ” 反引号括起来的也是一条命令, Shell 先执行该命令,然后将输出结果立刻代换到当前命令行中。例如 . 定义一个变量存放 date 命令的输出: user02$ DATE=`date` user02$ echo=$DATE #$变量名:变量的值 命令代换也可以用 S() 表示 : user02$ DATE=$(date) 算数代换: 使用 $(()) ,用于算术计算, (()) 中的 Shell 变量取值将转换成整数,同样含义的 $[ ] 等价例如 : user02$ VAR=45 user02$ echo $(($VAR+3)) # 等价 $((VAR+3)) 或 $[VAR+3] S(())) 中只能用 +-*/ 和 () 运算符,并且只能做整数运算 S[base#n], 其中 base 表示进制, n 按照 base 进制解释,后面再有运算数,按十进制解释 user02$ echo $[2#10+3] # 二进制 10 ,然后+ 3 user02$ echo $[8#10+3] # 八进制 10 ,然后 +3 转义字符: 和 C 语言类似, \ 在 Shell 中被用作转义字符,用于去除紧跟其后的单个字符的特殊意义 ( 回车除外 ) ,换句话说,紧跟其后的字符取字面值。例如 : user02$ echo \$PATH user02$ \\ 创建文件 --test touch --test # 报错 单引号: Shell 脚本中的单引号和双引号一样都是字符串的界定符,而不是字符的界定符。单引号用于保持引号内所有字符的字面值,即使引号内的 \ 和回车也不例外,但是字符串中不能出现单引号。如果引号没有配对 就输入回车, Shell 会给出续行提示符,要求用户把引号配上对。例如 : user02$ echo "abcde" user02$ echo 'abcd' 双引号: 被双引号括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。单引号不能展开变量。 user02$ VAR=`date` user02$ echo "$VAR" 2022 年 09 月 17 日星期六 10:22:52 CST user02$ echo "${VAR}" 2022 年 09 月 17 日星期六 10:22:52 CST user02$ echo 'VAR' user02$ echo '${VAR}' 4.脚本语法: 条件测试: 命令 test 或 [ 可以测试一个条件是否成立,如果测试结果为真,则该命令的 Exit Status 为 0 ,如果测试结果为假,则命令的 Exit Status 为 1 。例如测试两个数的大小关系 : user02$ VAR=2 user02$ test $var -gt 1 user02$ echo $? 常见的测试命令如下表所示 : [ -d DIR ]如果DIR存在并且是一个目录则为真 [ -f FILE ]如果FILE存在且是一个普通文件则为真 [ -z STRING ]如果STRING的长度为零则为真 [ -n STRING ]如果STRING的长度非零则为真 [ STRING1 = STRING2 ]如果两个字符串相同则为真 [ STRING1 != STRING2 ]如果字符串不相同则为真 [ ARG1 OP ARG2 ] ARG1和ARG2应该是整数或者取值为整数的变量,op是-eq (等于) -ne (不等于) -lt (小于) -le (小于等于) -gt (大于) -ge (大于等于)之中的一个。 和 C 语言类似,测试条件之间还可以做与、或、非逻辑运算 : [ ! EXPR ] EXPR 可以是上表中的任意一种测试条件, ! 表示 “ 逻辑反 ( 非 )” 。 [ EXPR1 -a EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-a表示“逻辑与” [ EXPR1 -o EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-o表示“逻辑或” 示例如下所示: $ VAR=abc $ [ -d user02 -a $VAR = 'abc' ] $ echo $? 4.分支: if/then/elif/fi: 和 C 语言类似,在 Shell 中用 if 、 then 、 elif 、 else 、 fi 这几条命令实现分支控制。这种流程控制语句本质上也是由若干条 Shell 命令组成的 if [ -f ~/.bashrc ] ; then . ~/.bashrc fi 其实是三条命令, if [ -f ~/.bashrc ] 是第一条, then . ~/.bashrc 是第二条, fi 是第三条。如果两条命 令写在同一行则需要用 == ; == 号隔开,一行只写一条命令就不需要写 == ; == 号了,另外, then 后面有换行,但这条命令没写完, Shell 会自动续行,把下一行接在 then 后面当作一条命令处理。和 [ 命令一 样,要注意命令和各参数之间必须用空格隔开。 if 命令的参数组成一条子命令,如果该子命令的 Exit Status 为 0 ( 表示真 ) ,则执行 then 后面的子命令,如果 Exit Status 非 0 ( 表示假 ) ,则执行 elif 、 else 或者 fi 后面的子命令。 if 后面的子命令通常是测试命令,但也可以是其它命令。 用 fi 表示 if 语句块的结束。见下例 : #! /bin/bash
if [ -f test.c ];then
echo "test.c is a file"
else
echo "test.c is not a file"
fi “== : ==” 是一个特殊的命令,称为空命令,该命令不做任何事,但 Exit Status 总是真。 echo "Is it morning? Please answer yes or no. "
read YES_OR_NO
if [ "$YES_OR_NO" = "yes" ]; then
echo "Good morning!"
elif [ "$YES_OR_NO" = "no" ]; then
echo "Good afternoon!"
else
echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
return ;
fi 上例中的 read 命令的作用是等待用户输入一行字符串,将该字符串存到一个 Shell 变中。 此外, Shell 还提供了 && 和 || 语法,和 C 语言类似,具有 Short-circuit 特性,很多 Shell 脚本喜欢写成这样 : test "$(whoami)" != 'root' && (echo you are using a non-privileged account;) && 相当于 “if...then..." 而 || 相当于 “if not...then..." && 和 || 用于连接两个命令,而上面讲的 -a 和 -o 仅用于在测试表达式中连接两个测试条件,要注意它们的区别,例如 : test "$VAR" -gt 1 -a "$VAR" -lt 3 示例如下: #! /bin/bash
echo "请输入你要判别的文件名: "
read file_ name
if [ -f "$file_ name" ]; then
echo 'it is a file
elif [ -d "$file_ nane" ]; then
echo 'It is a dir'
elif [ -p $file_ _name ] ; then
echo 'It is pipe
else
echo 'it is not a known file'
exit 1
fi case/esac: case 命令可类比 C 语言的 switch/case 语句, esac 表示 case 语句块的结束。 C 语言的 case 只能匹配整型或字符型常量表达式,而 Shell 脚本的 case 可以匹配字符串和 Wildcard , 每个匹配分支可以有若干条命令, 末尾必须以 ;; 结束 ,执行时找到第一个匹配的分支并执行相应的命令,然后直接跳到 esac 之后,不需要 像 C 语言一样用 break 跳出 示例如下: #! /bin/bash
echo "Is it morning? Please answer yes or no."
read YES_OR_NO
case "$YES_OR_NO" in
yes|y|Yes|YES)
echo "Good Morning!";;
[nN][oO])
echo "Good Afternoon!";;
*)
echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
return 1;;
esac
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
