为了在Linux下使用shell编程,需要掌握这些基础知识
在Linux下使用shell编程往往可以让我们的工作变得轻松很多。以下必要的知识你都掌握了吗?
输入参数和默认变量
在shell脚本中,有些内容是专门用来处理参数的,它们都有特定的含义,例如:
/home/shouwang/test.sh para1 para2 para3
$0 $1 $2 $3
脚本名 第一个参数 第三个参数其中$0代表要运行的脚本名称,$1 $2代表第一个和第二个参数。另外,还有一些其他的默认变量,比如:
# 代表脚本后面跟的参数个数,前面的例子中有3个参数
$@ 代表了所有参数,并且可以被遍历
$* 代表了所有参数,且作为整体,和$*很像,但是有区别
$$ 代表了当前脚本的进程ID
$? 代表了上一条命令的退出状态变量
给变量赋值,使用等号,但是等号两边不能有空格,等号字符串右侧有空格的字符串也必须用引号引起来:
para1="hello world" #字符串直接赋给变量para1unset 用于停用变量。例如:
unset para1如何使用变量?使用变量时,需要在变量前添加$。例如,如果要打印上一段内容1:
echo "para1 is $para1"
#将会输出 para1 is hello world或在变量名称两边添加大括号:
echo "para1 is ${para1}!"
#将会输出 para1 is hello world!执行命令
如果要在 shell 中运行命令,通常只要像在终端中一样执行命令即可,但是如果你想打印命令的结果,这个方法就行不通了。因此,shell 命令方法通常包括:
a=`ls` #`是左上角~键,不是单引号或使用 $ 后跟括号中的命令:
echo "current path is $(pwd)" #另外,前两种方法不适用于计算表达式,必须使用以下方法:
echo "1+1=$((1+1))" #打印:1+1=2即,在 $ 后面使用 双括号将要计算的表达式 括起来。
如果要执行的命令存储在变量中怎么办?以前的方法不再可行。当然,括号内的内容仍然是作为命令执行的。比如要使用下面的方法:
a="ls"
echo "$($a)"但是,如果字符串中包含多个命令,上面的方法就不可行了,必须使用下面的方法:
a="ls;pwd"
echo "$(eval $a)"这个使用eval来改变item的内容都是作为命令执行。
条件分支
一般描述,如果语句执行成功,返回值为0,否则为非0。因此,执行上一条命令的结果可以如下判断:
if [ $? -eq 0 ]
then
echo "success"
elif [ $? -eq 1 ]
then
echo "failed,code is 1"
else
echo "other code"
ficase命令的使用方法如下:
name="aa"
case $name in
"aa")
echo "name is $name"
;;
"")
echo "name is empty"
;;
"bb")
echo "name is $name"
;;
*)
echo "other name"
;;
esac初学者要特别注意以下几点:
- []前面必须有一个包含逻辑表达式
- if 的空格必须跟在 elif 后面,后面跟要执行的命令
- 要打印上一个命令的执行结果,最好赋值 $ ?到一个变量,因为一旦执行该语句,$? 的值就被改变了。它可能会改变。
- 每个 case 分支都以两个分号结尾,最后一个 case 反向书写,即 esac。
如何使用多个条件?有两种方法。方法一:
if [ 10 -gt 5 -o 10 -gt 4 ];then
echo "10>5 or 10 >4"
fi方法二:
if [ 10 -gt 5 ] || [ 10 -gt 4 ];then
echo "10>5 or 10 >4"
fi其中 -o 或 ||意味着或。还有一些常见的条件句。
总结如下:
- -o或or,同||
- -a和a,同&&
- ! no-
整数判断:
- -eq 两个数是否相等
- -no 这两个数是否不相等
- -gt 第一个是否大于第二个(也更大)❙⼼ - lt 第一个是否小于第二个(小于)
- -ge 第一个是否大于或等于第二个(大于或等于)
- -le 第一个是否小于或等于第二个(小于或等于)
计算字符串 str1 exp str2:
- -z "$str1" str1 是否为空字符串
- -n " $str1" str1 是否不是空字符串
- "$str1" == "$str2" str1是否等于str2
- "$str1" != "$str2" str1是否不等于str2
- " $str1" =~ " str2" str1是否包含str2
特别注意,字符串变量最好用引号括起来,因为一旦字符串中有空格,这个表达式就会出错,有兴趣的话可以尝试比较 str1="hello world" 和 str2="hello" 的情况。
评估文件目录:file_name
- -f $filename 文件是否存在
- -e $filename 是否存在
- -d $filename 目录
- 文件是否存在且不为空
- ! -s $filename 文件是否为空
循环
循环一与 Python 非常相似:
#遍历输出脚本的参数 for i in $@; do echo $i done循环二与 C 风格非常相似:
for ((i = 0 ; i < 10 ; i++)); do echo $i done打印循环 0。
重复形式三:
for i in {1..5}; do echo "Welcome $i" done循环打印 1 至 5。
循环方法四:
while [ "$ans" != "yes" ] do read -p "please input yes to exit loop:" ans done仅当输入 yes 时才会退出循环。这意味着当条件满足时,循环就会被执行。
第五种迭代方法:
ans=yes until [ $ans != "yes" ] do read -p "please input yes to exit loop:" ans done这意味着只有当ans不为yes时才会退出循环。
重复方法六:
for i in {5..15..3}; do echo "number is $i" done每5打印一次,即打印5,8,11,14。
函数
定义函数如下:
myfunc() { echo "hello world $1" }或者:
function myfunc() { echo "hello world $1" }函数调用:
para1="shouwang" myfunc $para1返回值 返回值
通常只支持返回值 5 来获取返回值, 这个可以通过以下方式进行。
function myfunc() { local myresult='some value' echo $myresult } val=$(myfunc) #val的值为some value返回方法适合判断函数执行是否成功:
function myfunc() { #do something return 0 } if myfunc;then echo "success" else echo "failed" fi注释
Shell使用#来注释内容行。我们之前见过:
#!/bin/bash # 这是一行注释 :' 这是 多行 注释 ' ls :<<eof 这也可以 达到 多行注释 的目的 EOF</eof日志保存
运行脚本后,不可避免地要记录日志。最常见的方法是重定向。以下面的脚本为例:
#!/bin/bash #test.sh lll #这个命令是没有的,因此会报错 date方法一,将标准输出保存到文件中,并打印标准错误:
./test.sh > log.dat这种情况下,如果命令执行过程中出现错误,则会将错误打印到控制台。因此,如果您从程序中调用它,则不会记录任何错误消息。
方法二,标准输出和标准错误保存到日志文件中:
./test.sh > log.dat 2>&12>&1 可参考《如何理解linuxshell中的2>&1》
方法三,保存日志文件时,输出也是到控制台:
./test.sh |tee log.dat脚本 最常见的执行方式
我们已经见过:
./test.sh其他执行方式:
sh test.sh #在子进程中执行 sh -x test.sh #会在终端打印执行到命令,适合调试 source test.sh #test.sh在父进程中执行 . test.sh #不需要赋予执行权限,临时执行脚本退出代码
很多时候我们需要获取脚本执行的结果,即退出位置。通常0表示执行成功。 0位表示失败。要获取退出代码,我们需要使用 exit。例如:
#!/bin/bash function myfun() { if [ $# -lt 2 ] then echo "para num error" exit 1 fi echo "ok" exit 2 } if [ $# -lt 1 ] then echo "para num error" exit 1 fi returnVal=`myfun aa` echo "end shell" exit 0这里需要特别注意的是,当你使用
returnVal=`myfun aa`这样的语句来执行函数时,即使是在exit函数中,也并没有结束脚本的执行,只是退出该函数。这是因为退出意味着退出当前进程,这样执行函数相当于fork子进程,所以当前脚本不会退出。最终结果将被看到,无论你的函数的参数是什么,终端 shell 都会打印它。
./test.sh;echo $? 0总结
以上就是shell编程最基本、最重要的内容。当然,这还不是全部。例如字段、字典、参数处理等就不详细介绍了。由于篇幅有限,将在后续文章中详细介绍。学好shell,放松双手。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网