Linux Shell编程

一、什么是Shell
在Linux中,系统会为每个用户运行一个shell(外壳)程序。
shell程序是一个命令行解释器,交互式地解释和执行用户输入的命令。
shell还是一种解释性的程序设计语言,定义了变量和函数,数组,程序控制结构等很多高级语言支持的特性。

二、shell编程用在什么地方
shell一般用于批量命令执行,用来管理,监控系统等。

三、shell语法详解
1.程序示例,输出"hello world"
firstshell

#!/bin/bash
echo "hello world"

改变文件的访问权限,使其具有可执行属性
chmod +x firstshell

输出结果:

程序的第一行必须是 #!/bin/bash
指定系统用#!后的命令/bin/bash来运行此文件。

2.变量
varname=值
需要注意的是:
1)"="前后不能有空格
2)变量默认都是字符串格式的
3)使用变量,必须加上"$"符号,否则取到的是变量名本身
4)若变量名和其他字符串混淆在一起时,需要加上{}来区分变量名
如下例所示:
myshell

#!/bin/bash
var1=1
var2=2
var3=$var1+$var2 #变量默认是字符串,所以输出为1+2
var4 =4 #等号前后有空格,报错
echo $var1
echo $var2
echo $var3
echo $var4
echo "var1 is the ${var1}st"

输出结果:

那么,我们如何将var1,var2作为数值类型来相加呢?
方法一:使用C风格表示式,((表示式))
((var3=$var1+$var2))
或((var3=var1+var2))

方法二:使用shell中的let命令
let 'var3=var1+var2' #注意不能加'$'符号,否则报错

方法三:调用expr外部程序,效率较低,尽量少用
var3=$(expr $var1 + $var2) #expr函数需要三个参数,$var1,+,$var2

3.流程控制
1)if语句
结构如下:

if
then
elif
then
else
fi

或者(then写在if的后面,但是要加分号;)

if ...;then
elif...;then
else
fi

示例如下:
myshell

#!/bin/bash
var1=1
var2=2
if ((var1==var2))
then
    echo "var1=var2"
elif ((var1>var2))
then
    echo "var1>var2"
else
    echo "var1<var2"
fi

输出结果:

bash中有一些常用的条件判断表达式,使用方法:[ 条件判断表达式 ]
-f "filename":判断是否是文件
-x "/bin/ls":判断/bin/ls是否存在并有可执行权限
-n "$var":判断$var变量是否有值
"$a"=="$b":判断$a和$b是否相等

2)&&和||操作符
&&:逻辑与操作符
||: 逻辑或操作符

3)case语句
case表达式用来匹配给定的字符串,和C中的switch...case匹配的是数字不同。

case ... in
...) 
    do something;;
...)
    do something;;
esac

下例中,我们写了一个程序,用来解压bzip2,gzip,zip类型的压缩文件。
代码如下:

#!/bin/bash
ftype=$(file $1)
echo "$ftype"
case "$ftype" in
"$1: Zip archive"*)
    unzip "$1";;
"$1: gzip compressed"*)
    gunzip "$1";;
"$1: bzip2 compressed"*)
    bunzip2 "$1";;
*)
    echo "File $1 can not be unconpressed";;
esac

输出结果:

其中$1表示输入的第一个参数

4)select循环语句
select循环适合交互式的场合,格式如下:

select var in ...;do
...
done

示例代码如下:

#!/bin/bash
echo "what is your favourite OS?"
select var in "RedHat" "Ubuntu" "Free BSD" "Other";do
    echo "hello $var"
    break;
done
echo "you have selected $var"

输出结果:

5)while/for循环
while循环

while...;do
    ...
done

for循环

for var in ...;do
    ...
done

示例代码如下:

#!/bin/bash
for var in A B C;do
    echo "var is $var"
done

输出结果:

4.shell里的一些特殊符号
1)*:表示通配符
双引号可以防止通配符但允许变量扩展
单引号(或转义字符\)的限制更严格,可防止任何变量扩展;
示例代码如下:

#!/bin/bash
echo *.c
echo "*.c"
echo '*.c'
echo \*.c

echo $SHELL
echo "$SHELL"
echo '$SHELL'
echo \$SHELL

输出结果:

2)命令行参数
$1:命令行的第一个参数
$#:命令行参数的个数
$@:命令行的所有参数
$*:所有命令行参数作为一个参数
shift n:去掉前面的n个参数

示例如下:

#!/bin/bash
help()
{
cat << HELP
   本例程序用来获取命令行参数
   使用了命令:myshell -l hello -f -- -somefile1 somefile2
HELP
   exit 0
}
while [ -n "$1" ]; do
case "$1" in
   -h) help;shift 1;; 
   -f) opt_f=1;shift 1;; 
   -l) opt_l=$2;shift 2;; 
   --) shift;break;; 
   -*) echo "error: no such option $1. -h for help";exit 1;;
   *) break;;
esac
done
echo "opt_f is $opt_f"
echo "opt_l is $opt_l"
echo "first arg is $1"
echo "2nd arg is $2"

输出结果:

3)输出段落
echo一次只能输出一行
如果是一段文字,该如何输出呢?
我们可以使用cat <<,后接一个字符串,段落的末尾再加上这个字符串来输出段落。

cat << HELP
...
...
HELP

下例中,程序用来替换文件名,
有三个输入参数,第一个参数是待替换字符
第二个参数是替换字符
第三个参数是文件名。

#!/bin/bash
if [ $# -lt 3 ];then
cat << HELP
本例中,程序用来替换文件名,
有三个输入参数,第一个参数是待替换字符
第二个参数是替换字符
第三个参数是文件名。
HELP
   exit 0
fi
OLD="$1"
NEW="$2"
# The shift command removes one argument from the list of
# command line arguments.
shift
shift
# $@ contains now all the files:
for file in "$@"; do
   if [ -f "$file" ]; then
      newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
      if [ -f "$newfile" ]; then
       echo "ERROR: $newfile exists already"
      else
         echo "renaming $file to $newfile ..."
         mv "$file" "$newfile"
      fi
   fi
done

输出结果:

5.函数
格式如下:

函数名(){
    #函数中$1,$2对应接收到的第一第二个参数
}

示例代码如下:

#!/bin/bash
add()
{
    
    echo $(($1+$2))
}
var1=1
var2=2
add $var1 $var2

输出结果:

四、脚本调试
最简单的方式是使用echo输出值。

五、Shell编程示例
我们有一个日志文件,保存了系统的操作记录。过了一段时间后,这个文件可能会变得很大。
我们采取的做法是重命名该文件,然后生成一个新的文件供再次使用。
重命名的规则是,当前文件log.txt重名为log1.txt,在此之前,如果已经有log1.txt时,将log。txt命名为log2.txt,依次类推。
代码如下:

#!/bin/bash
help()
{
   cat << HELP
重命名该文件,然后生成一个新的文件供再次使用。
重命名的规则是,当前文件log.txt重名为log1.txt,在此之前,如果已经有log1.txt时,将log。txt命名为log2.txt,依次类推。
HELP
   exit 0
}

if [[ $1 == '-h' || $1 == '' ]]; then
  help
fi

filename=$1

# 我们先找到最大的数字再说。
max=0
while [ -f "$filename.$((++max))" ]; do
  : # 什么都不用做,我们已经顺手用 ++max 自增了 max 了。
done

# 然后从最大的一路重命名下来。
for ((i=max; i>0; i--)); do
  # 数字加个 1,好给前一个让位子。
  if [ -f $filename.$i ];then 
      mv "$filename.$i" "$filename.$((i+1))"
  fi
done
 
# 最后我们点名要重命名的:
if [ -f "$filename" ]; then
   mv "$filename" "$filename.1"
fi

# 重新创建一下。
: > "$filename"

运行程序,./myshell log.txt


我们会发现log.txt的日志文件的名称会加1,同时当前的log.txt文件会变成log.txt.1,
生成一个全新的log.txt文件,供程序再次使用。

posted on 2016-06-29 15:33  迪米特  阅读(441)  评论(0编辑  收藏  举报

导航