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

你可能感兴趣的:(linux,学习)