linux shell程序设计

  • shell是unix和linux内核的外壳,它构成了命令或者程序的一个执行环境。不同版本的Unix和linux的shell各有特色,但是都提供了linux命令解释执行的一个基本工作环境。
  • shell脚本程序是利用shell的语法功能所写的一个程序,它是一个纯文本文件,类似于windows环境下的.bat文件,可以让系统自动执行写在shell脚本中的命令,比起windows环境下的.bat文件,它更加类似于高级语言,它可以执行分支、循环、函数等功能。
  • shell是一种解释型程序,不需要经过编译就可以执行。
  • 在centos中执行shell脚本文件的时候,要注意linux并不会默认当前的路径为可以执行的目录,它的所有的可执行文件都会搜索系统的环境变量(可以使用env | grep PATH 查询),环境变量PATH的值指定了可执行的文件的搜索路径。对于以上情况可以有以下的解决方案:
    ① 把当前路径变成可搜索路径(有风险)
    ② 把当前文件移动到可搜索路径下
    ③ 使用./filename
  • 当前路径为可搜索路径后,可以直接输入还是会出错,以为没有执行的权限,有两种解决方法,
    ① chomd修改权限
    ② 使用sh filename,把文件变成sh的一个参数输入

shell变量

在shell中,所有的变量都没有定义变量类型,所有的变量都会被看做为字符串变量;在变量名前面加上美元符号$,可以引用变量的值。

[root@aubin s]# a=456 # 定义一个字符串变量a
[root@aubin s]# echo $a #把变量a的内容输出
456

echo表示输出一个数据

注意以下三条指令的不同

echo $a # 表示输出a这个变量
echo "$a" # 表示输出a这个变量
echo '$a' # 表示输出 $a 这个字符串

使用指令read 可以从键盘中输入一个变量的值,如下:

[cch@aubin s]$ read b
www
[cch@aubin s]$ echo 'b='$b
b=www

if分支语句

使用[]构成条件分支判断,if 和 fi是成对出现的,而且该语句不能随意的添加或者删减空格。

echo "Is it morning? Please answer yes or no!"
read timeofday
if [$timeofday="yes"];then
	echo "Good morning!"
else
	echo "Good afternoon!"
fi

exit 0

如果then是单独一行,可以不用分隔符

echo "Is it morning? Please answer yes or no!"
read timeofday
if [$timeofday="yes"]
then
        echo "Good morning!"
else
        echo "Good afternoon!"
fi

exit 0

不使用中括号,使用test也可以实现条件语句的编写,但是使用test没有方括号直观

echo "Is it morning? Please answer yes or no!"
read timeofday
if test $timeofday="yes"
then
        echo "Good morning!"
else
        echo "Good afternoon!"
fi

exit 0

多分支语句的编写可以使用elif

echo "Is it morning? Please answer yes or no!"
read timeofday
if [$timeofday="yes"]
then
        echo "Good morning!"
elif [$timeofday="no"]
then
        echo "Good afternoon!"
else
        echo "The answer can not recognize, plese enter again!"

fi

exit 0

判断文件

if [ -f ./pp ] # 判断文件是否存在
then
	echo "pp exists"
fi

if [ -d ./pp ] # 判断文件是否是一个目录,注意中括号与周围的空格
then
	echo "pp is a directory"
else
	echo "pp is a file"
fi
exit 0

if/while语句可以使用以下几种类型的判断

  • 数值比较:-eq(等于)、-ne(不等于)、-gt(大于)、-ge(大于等于)、-lt(小于)、-le(小于等于)
  • 字符串比较:=(等于)、!=(不等于)、-z(字符串长度为零)、-n(字符串长度不为零)
  • 文件测试:-e(文件存在)、-d(目录存在)、-f(文件是否为文本)、-r/-w/-x(文件是否可读/可写/可执行)
  • 逻辑运算:&&(与)、||(或)
  • 其他特殊操作符:()(子shell)、[](数组)

case语句

case语句更加适用于多分支语句中

echo "Is it morning? Please answer yes or no"
read timeofday
case "$timeofday" in
	"yes" ) echo "Good Morning";;
	"no" ) echo "Good Afternoon";;
	* ) echo "Please enter again";;
esac
exit 0

多个值匹配

echo "Is it morning? Please answer yes or no"
read timeofday
case "$timeofday" in
        yes | Yes | Y ) echo "Good Morning";;
        n* | N* ) echo "Good Afternoon";;
        * ) echo "Please enter again";;
esac
exit 0

使用正则表达式

echo "Is it morning? Please answer yes or no"
read timeofday
case "$timeofday" in
        [Yy][Ee][sS]| [Yy]  ) echo "Good Morning";;
        [nN][oO] |[Nn]  ) echo "Good Afternoon";;
        * ) echo "Please enter again";;
esac
exit 0

for循环

  • foo是一个循环变量,
  • in是关键字,in后面的内容表示循环每一次的值,前面说到,shell的变量都是字符串,所以要循环什么就要在in后面写什么。
  • do …… done中间的表示循环体
for foo in 1 2 34 # 一共循环三次,in 后面的是循环变量的取值,都为字符串
do
	echo $foo
done
exit 0

$(...),以…中的命令的执行结果作为shell变量的取值;除了使用以上的形式,还可以使用esc下面的单引号包括住所需要执行的命令。

for fo in $(ls p*)
do
	echo $fo
done
exit 0
for fo in `ls p*`
do
	echo $fo
done
exit 0

while循环

echo "Action!"
read temp

while [ "$temp" != "hello" ]
do
        echo "Plase enter again!"
        read temp
done
echo $temp
exit 0

分支判断采用表达式值的判断方式

-le表示小于等于

foo=1
while [ "$foo" -le 20 ]
do
        echo " $foo : Try again "
        foo=$(($foo + 1))
done
exit 0

跳出循环

  • break:跳出当前循环(break默认表示跳出一层循环,break2表示跳出两层循环)
  • exit:退出当前脚本,不再执行exit下方的任何语句
  • continue:忽略本次循环结果,继续执行循环

位置参数

位置参数是指函数调用是参数的位置决定其对应的值,在shell中,位置参数从$1开始

  • 无论是函数内部还是函数的外部, $0都表示程序名
  • $@或者$*可以一次性获取所有的参数;
  • $#获取参数的个数
  • ${10}获取第10个参数
# $0表示函数名; $1表示程序的第一个参数,$i表示程序的第i个参数;参数与其在命令行的位置有关
echo $0 $1
# 例如 ls -la 的命令,$0=ls $1=-la

代码示例1:

#! /bin/bash
# 这里表示命令行的位置参数,从命令行内键入
echo $0
echo $1
echo $2
echo $3

foo()
{
	# 这里表示函数的位置参数,从函数调用中键入
    echo $0
    echo $1
    echo $2
    echo $3
    echo $4
    echo "function foo\n"
}

echo "---start---"
foo 11 22 33 44
#foo $0 $1 $2 $3 $4
echo "---end---"


# 输出结果
[cch@aubin s]$ ./pp aa bb cc dd
./pp
aa
bb
cc
---start---
./pp
11
22
33
44
function foo\n
---end---
[cch@aubin s]$ 

代码示例2:

#! /bin/bash

echo $0
echo $1
echo $2
echo $3

foo()
{
    echo $0
    echo $1
    echo $2
    echo $3
    echo $4
    echo "function foo\n"
}

echo "---start---"
#foo 11 22 33 44
foo $0 $1 $2 $3 $4 # 这里调用的是命令行的位置参数,从命令行中键入,把命令行中的参数作为函数的参数给函数foo调用
echo "---end---"
# 输出结果
[cch@aubin s]$ ./pp aa bb cc dd
./pp
aa
bb
cc
---start---
./pp
./pp # $1的输入结果
aa
bb
cc
function foo\n
---end---
[cch@aubin s]$ 
  • 其实位置函数不仅仅是shell的专利,c语言中,我们常看到int main(int argc,char **argv)这样的main函数,这样的main函数也可以从命令行中读取参数,其中argc表示参数的个数这个参数的个数包括了要执行的程序的名字(也就是argc=实际参数的数量+1);argv就是实际传入的参数。
  • 与shell一样,argv[0]表示要执行的程序本身的名字,argv[n]表示要传入的第n个参数。
#include<stdio.h>
#include<stdlib.h>


int main(int argc,char **argv){
	printf("argc=%d\n",argc);
	printf("argv=%s\n",argv[0]);
	printf("%s\n",argv[1]);
	return 0;
}
[cch@aubin s]$ gcc file.c
[cch@aubin s]$ ./a.out cch1 cch2 
argc=3 # 输入两个参数为cch1和cch2,但是程序本身./a.out也包括在argc数目内
argv=./a.out # 程序名称
cch1 # 第一个参数

函数

fun(){}表示是一个函数,大括号之间的内容表示是一个函数体

fun(){
        echo "This is fun function!"

}

echo "starting"
fun # 程序本身不会执行,只有当被调用才会开始执行
echo "ending"

exit 0

传递参数

fun(){
        echo "This is fun function!"
        echo $1 # 获取位置参数,表示是函数内的第一个参数
}

echo "starting"
fun "data"
echo "ending"

exit 0

# 这里是输出的结果
[cch@aubin s]$ ./pp
starting
This is fun function!
data
ending

注意,程序的位置参数与函数内的位置参数不是一个概念,出现在函数调用中的$1表示的是程序的位置参数,与在命令行中的第一个参数是一样的;

fun(){
        echo "This is fun function!"
        echo $2 # 获取位置参数
}

echo "starting"
fun "data" $1 #表示命令行的第一个位置参数
echo "ending"

exit 0

# 这里是输出的结果
[cch@aubin s]$ ./pp
starting
This is fun function! # 空行表示没有第二个命令参数

ending

流编辑器

sed工具

  • sed是一个“流编辑”工具,它不面向屏幕,而且非交互式。流编辑器非常适合于执行重复的编辑,这种重复的编辑如果由人工完成将花费大量的时间。
  • sed使用工具按照顺序逐行将文件读入到内存中,然后,他执行该行的所有指定的操作,并且在完成请求的修改之后将该行返回内存中,以将其转储到中断。完成这一行的所有操作之后,它读取文件的下一行,重复以上步骤,知道它完成整个文件。sed默认把内容输出到屏幕,保持源文件不会被修改。

sed的语法:sed [options] '{command}' [filename]

-e 表示后面的指令同步执行
[cch@aubin ~]$ echo "the tiger cubs will meet on Tuesday after scool" | sed -e 's/tiger/wolf/' -e 's/after/before/'
the wolf cubs will meet on Tuesday before scool

awk工具

awk是一个优秀的样式扫描与处理工具,其功能大大强与sed和grep;awk几乎可以完成grep和sed所能完成的全部的工作,同时它号可以进行样式的装入、流控制、数学运算符、进程控制语句甚至内置的变量和函数。它具备了一个完整的语言所应该具备的几乎所有的特性。awk有自己的程序设计语言为 样式扫描和处理语言。

awk [-F separator] ‘pattern’ {action}’ filename

$1 表示第一列的意思,匹配搭配 :0 行,并且输出第一列的信息
[cch@aubin ~]$ who | awk '/:0 /{print $1}'
cch

应用示例

which命令的shell脚本实现

which主要是用来查找一些可执行文件的存放在哪一个可执行的路径下。

[cch@aubin ~]$ which file
/usr/bin/file
# 以上系统命令可以使用sed来实现
for i in `env | grep PATH | sed -e 's/^PATH=//' -e 's/:/ /g'`
do
find $i -name $1 -print 2>/dev/null
done
[cch@aubin s]$ ./pp file
/usr/bin/file
[cch@aubin s]$ 

以上命令的意思是:

  • `表示单引号内的都是可执行的命令
  • env是一个系统命令,用于查找当前系统的可执行路径
  • env | grep PATH | sed,把env的结果作为右边的输入,检查env输出中的PATH匹配项,并且给到sed
  • -e 表示两个指令同步执行
  • 's/^PATH=//'把首字串为PATH=的替换成空
  • 's/:/ /g'把所有的冒号替换成空格,并且全文替换。
  • find $i -name $1 -print把输入的第一个参数作为find的查找,去查找到对应的结果并且输出
  • 2>/dev/null可能会出现错误,把错误重定向/dev/null中,避免屏幕显示出错误
# 还可以使用awk来实现,awk有内嵌的函数
for i in `set | grep PATH |awk  '{sub(/^PATH=/,"")}{gsub(/:/," ")}{print $0}'`
do
find $i -name $1 -print 2>/dev/null
done
exit 0

以上的命令解释如下:

  • subgsub是awk内嵌的两个函数,前者表示替换,后者表示全文替换
  • {print $0}表示输出全部的列,作为in 后面的内容
  • set与env的命令是一样的

讨论

问题一:如何定义和使用shell变量,给出一个例子

讨论:使用shell变量有三种方法,一种是用等号直接赋值,比如a=123;第二种是从键盘中读入,比如read b;第三种是使用for循环变量,比如 for i in a b c,可以对i循环赋值为a b c。

问题二:if/while语句可以利用多少种类型的判断?

讨论:if/while语句可以有三种类型的判断,一种是字符串的判断,比如判断写入的数据是否是yes/no;第二种是文件的判断,比如使用 -f 判断文件是否存在,使用 -d 判断文件是否是一个目录;第三种是判断一个值是否相等,shell变量虽然都是字符串,但是可以使用$()对字符串取值。

问题三:什么是正则表达式,怎么样使用正则表达式去匹配得更加清楚

讨论:正则表达式可以用来匹配符合某一种规则的字符,以case语句中,需要匹配no的各种大小写的可能性,可以使用正则匹配 [Nn][Oo] | [Nn] ,这样可以使得条件表达式更加简洁。

问题四:程序(可执行文件)的参数是什么,函数的参数是什么,举例说明如何使用这些参数。

讨论:程序的位置参数和函数的位置参数是不同的,①程序的参数指的是整一个程序(命令的)参数,比如在命令行中输入ls -la ,该命令中的 -la 就是该命令的第一个参数,用 $1 表示;②函数的参数表示函数调用时传递的参数,跟在函数调用的后面。

问题五:什么是sed,什么是awk,举例说明怎么使用他们

讨论:详情看上面的介绍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值