Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
注意:
Shell 脚本(shell script),是一种为 shell 编写的脚本程序。
业界所说的 shell 通常都是指 shell 脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。
由于习惯的原因,简洁起见,此博客出现的 "shell编程" 都是指 shell 脚本编程,不是指开发 shell 自身。
Shell 编程跟 java、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Linux 的 Shell 种类众多,常见的有:Bourne Shell(/usr/bin/sh或/bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh)
此博客关注的是 Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的 Shell。
在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。
#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。
Shell编程同c语言有很多相似之处,但是在编写方式有许多不同,下面结合代码从7个方面说明。
在运行时,将Shell文件修改为可执行文件(chmod 7 my.sh);
1、变量
#!/bin/bash
# $# 是传给脚本的参数个数
# $0 是脚本本身的名字
# $1 是传递给该shell脚本的第一个参数
# $2 是传递给该shell脚本的第二个参数
# $@ 是传给脚本的所有参数的列表
# $$ 是脚本运行的当前进程ID号
echo "\$0 = $0"
echo "\$# = $#"
echo "\$$ = $$"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$@ = $@"
#注释:PS1为命令提示符,PS2一般为“>”,查看在终端:echo "$PS1",echo "$PS2";修改例如:PS1="name"
#注释:PATH 为环境变量,HOME 为家目录
echo "PATH = $PATH"
echo "HOME = $HOME"
str="hello"
val=100
mystr=$str
#注释:let 为加法操作 expr 也为加法操作
let "val+=1"
val=`expr $val + 1`
echo "val = $val"
#注释:read 接受用户输入,并将输入放入一个标准变量中
#注释:echo 、printf 同样都是输出语句
read line
echo "str = $str"
echo "val = $val"
echo "mystr = $mystr"
printf "line = $line\n"
运行结果:
2、条件语句 if
#!/bin/bash
#条件控制 if --> 'test' '[ ]'
#实现:对100分成绩分等级
echo "input:"
read line
if [ "$line" -gt 100 ] || [ "$line" -lt 0 ]
then
echo "error number"
exit 0
fi
if [ "$line" -gt 80 ]
then
echo "A"
elif [ "$line" -gt 70 ]
then
echo "B"
elif [ "$line" -gt 60 ]
then
echo "C"
else
echo "D"
fi
#几个小练习,判断数字相等,字符串相等
echo "input:"
read num
if [ "$num" -gt 100 ]
then
echo "$num< 100 "
else
echo "$num>= 100 "
fi
echo "input:"
read str
if [ "$str" = "abc" ]
then
echo "等于"
else
echo "不相等"
fi
echo "input:"
read num1
if test "$num1" = "123"
then
printf "==\n"
else
echo "!="
fi
运行结果:
3、循环语句 for while until
#!/bin/bash
#循环 for
for i in 1 2 3 4 5
do
echo "i = $i"
done
# $(ls)执行命令ls
for i in $(ls)
do
echo "i = $i"
sleep 1
done
#!/bin/bash
#循环 while
#输入密码,只有三次机会输入
i=1
while [ : ]
do
echo "input password:"
read pass
if [ "$pass" = "123456" ]
then
echo "success"
break
fi
if [ "$i" -eq 3 ]
then
echo "falied"
exit 0
fi
let "i++"
done
循环4次,每打印i的值睡一秒,i++
i=1
while [ "$i" -lt 5 ]
do
echo "i = $i"
sleep 1
let "i++"
done
运行结果:
#!/bin/bash
#循环 until
until [ -f "a.txt" ]
do
echo "not find a.txt"
sleep 1
done
echo "find a.txt"
运行结果:
4、cash语句
#!/bin/bash
#选择 case
echo "input:"
read line
case "$line" in
#[yY][eE][sS] | [yY]的意思时这些组合Yes yEs yeS YES yES YeS YES yes Y y都是成功
[yY][eE][sS] | [yY] ) echo "this is yes";;
[Nn][Oo] | [Nn] ) echo "this is no" ;;
* ) echo "****";;
esac
运行结果:
5、函数
#!/bin/bash
#函数:没有声明,所以写在前面
fun()
{
#在函数内部定义变量
#local可以改变str为局部变量
#local str=hello
str=hello
echo "fun \$# = $#"
echo "fun \$1 = $1"
echo "fun \$2 = $2"
echo "fun \$3 = $3"
echo "fun run"
#unset撤销掉str,函数结束则销毁str,后续操作无法访问str
#unset str
return 3
}
echo "myshell.sh run"
#函数普通调用
fun
#函数传参数调用
fun hello 123
#接受函数返回值
val=$?
echo "val=$val"
#外部接受函数内部变量值,str不是一个局部变量
echo "str=$str"
运行结果:
6、脚本调用脚本
文件:my.sh
#!/bin/bash
#脚本调用脚本
MYstr=hello
#export 设置环境变量
export MYstr
echo "myshell.sh run pid = $$"
echo "myshell.sh MYstr = $MYstr"
#调用a.sh,并传参“guowei”
./a.sh guowei
#调用a.sh,并传参“MYstr”
#./a.sh $MYstr
文件:a.sh
#!/bin/bash
echo "a.sh run pid = $$"
#用脚本传参数获取另一个脚本中的值
echo "a.sh MYstr = $1"
#通过环境变量获取另一个脚本变量
echo "a.sh Mystr = $MYstr"
运行结果:
7、AWK、SED
(1)AWK
awk 语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息。
awk 抽取信息后,才能进行其他文本操作。完整的 awk 脚本通常用来格式化文本文件中的信息。
有三种方式调用 awk,第一种是命令行方式,如:
awk [-F field-separstor] `commands` input-file(s)
这里,commands是真正的 awk命令。本章将经常使用这种方法。 [ - F域分隔符]是可选的,因为 awk 使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,但如果要浏览诸如 passwd 文件,此文件各域以冒号作为分隔符,则必须指明- F选项,如:awk -F: `commands` input-file(s)
具体实现:
第二种方法是将所有 awk 命令插入一个文件,并使 awk 程序可执行,然后用 awk 命令解释器作为脚本的首行,以便通过键入脚本名称来调用它。
文件:makedata.sh
#!/bin/bash
awk -F. '{print $1}' data > data1
awk -F. '{print $2}' data > data2
对比执行 makedata.sh 前后可以看到一下结果:
第三种方式是将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
- f选项指明在文件 awk-script-file 中的 awk 脚本,input-file(s)是使用 awk 进行浏览的文件名。
(2)SED
sed 是一个非交互性文本流编辑器。它编辑文件或标准输入导出的文本拷贝。标准输入可能是来自键盘、文件重定向、字符串或变量,或者是一个管道的文本。sed 可以做些什么呢? 别忘了,Vi也是一个文本编辑器。sed 可以随意编辑小或大的文件,有许多 sed 命令用来编辑、 删除,并允许做这项工作时不在现场。 sed 一次性处理所有改变,因而变得很有效,对用户来讲,最重要的是节省了时间。
sed 从文件的一个文本行或从标准输入的几种格式中读取数据,将之拷贝到一个编辑缓冲区,然后读命令行或脚本的第一条命令,并使用这些命令查找模式或定位行号编辑它。重复此过程直到命令结束。
调用 sed 有三种方式:
(1)在命令行键入命令;(2)将 sed 命令插入脚本文件,然后调用 sed;(3)将 sed 命令插入脚本文件,并使 sed脚本可执行。
使用 sed命令行格式为:
sed [选项] sed命令 输入文件
记住在命令行使用 sed 命令时,实际命令要加单引号。sed 也允许加双引号。
使用 sed 脚本文件,格式为:
sed [选项] -f sed脚本文件 输入文件
要使用第一行具有 sed 命令解释器的 sed 脚本文件,其格式为:
sed脚本文件 [选项] 输入文件
不管是使用shell命令行方式或脚本文件方式,如果没有指定输入文件,sed从标准输入中接受输入,一般是键盘或重定向结果。
sed 选项如下:
n 不打印;sed不写编辑行到标准输出,缺省为打印所有行(编辑和未编辑)。p命令可以 用来打印编辑行。
c 下一命令是编辑命令。使用多项编辑时加入此选项。如果只用到一条 sed命令, 此选项无用,但指定它也没有关系。
f 如果正在调用sed脚本文件,使用此选项。此选项通知 sed一个脚本文件支持所有的 sed 命令,例如:sed -f myscript.sed input_file,这里myscript.sed即为支持sed命令的文件。
保存sed输出
由于不接触初始化文件,如果想要保存改动内容,简单地将所有输出重定向到一个文件即可。下面的例子重定向 sed 命令的所有输出至文件‘ myoutfile’,当对结果很满意时使用这种方法。
sed 'some-sed-commands' input-file > myoutfile
下面是一些运用: