Linux-Shell脚本和RE

这里介绍ubuntu中shell脚本的相关基本知识即正则表达式的用法

1、记录命令历史

我们敲过的命令,linux是会有记录的,预设可以记录1000条历史命令。这些命令保存在用户的家目录中的.bash_history文件中。有一点需要你知道的是,只有当用户正常退出当前shell时,在当前shell中运行的命令才会保存至.bash_history文件中。

与命令历史有关的有一个有意思的字符那就是”!”了。常用的有这么几个应用:(1)!! (连续两个”!”),表示执行上一条指令;(2)!n(这里的n是数字),表示执行命令历史中第n条指令,例如”!100”表示执行命令历史中第100个命令;(3)!字符串(字符串大于等于1),例如!ta,表示执行命令历史中最近一次以ta为开头的指令。

2、管道

在处理数据时,需要经过几个步骤才能得到最终的数据,后面的命令需要用到前面命令输出的数据,这里就需要用到管道,管道符为|
用法:
command | command | command
ex:last | grep Fri 在last数据中查找含有Fri的行信息
ls -l | less 以less模式来阅读ls中的信息

3、管道命令

cut: 对数据进行分解,截取某一个字段
语法:cut -d “分隔字符” [-cf] n 这里的n是数字

-d :后面跟分隔字符,分隔字符要用双引号括起来
-c :后面接的是第几个字符
-f :后面接的是第几个区块

ex:ubuntu@ubuntu:~/Documents$ cat test4.text | cut -d ” ” -f1

sort :用做排序

语法:sort [-t 分隔符] [-kn1,n2] [-nru] 这里的n1 < n2
-t 分隔符 :作用跟cut的-d一个意思
-n :使用纯数字排序
-r :反向排序
-u :去重复
-kn1,n2 :由n1区间排序到n2区间,可以只写-kn1,即对n1字段排序

wc :统计文档的行数、字符数、词数,常用的选项为:
-l :统计行数
-m :统计字符数
-w :统计词数

uniq :去重复的行
-c :统计重复的行数,并把行数写在前面
-d:仅显示重复的行
-u:仅显示不重复的行
ex:ubuntu@ubuntu:~/Documents$ cat test4.text | sort | uniq
删除重复的行,前提是先排序

tee:将数据写入文件
-a: 写到文件尾部;默认从头开始写,会覆盖原有数据
-i: 忽略中断
ex:
ubuntu@ubuntu:~/Documents$ echo “nihaoa” | tee test1.text -a

tr:删除字符
tr -d “ ” :删除字符
tr -s “ ” “ ”:后面的字符代替前面的字符
ex:
ubuntu@ubuntu:~/Documents$ cat test1.text | tr -d “a”

ubuntu@ubuntu:~/Documents$ cat test1.text | tr -s “a” “b”

split:分割文件
-l: 以行数来分
-b :以文件大小来分
ex:
ubuntu@ubuntu:~/Documents$ split -l 1 test1.text
会自动生成分割后的几个文件

4、多条命令

平时我们都是在一行中敲一个命令,然后回车就运行了,那么想在一行中运行两个或两个以上的命令如何呢:
1、command1 ; command2
2、command1 && command2
3、command1 || command2

使用”;”时,不管command1是否执行成功都会执行command2; 使用”&&”时,只有command1执行成功后,command2才会执行,否则command2不执行;使用”||”时,command1执行成功后command2 不执行,否则去执行command2,总之command1和command2总有一条命令会执行。也可以用-a 和-o 代替and/or.

5、重定向

输入输出从定向

输入重定向用于改变命令的输入,输出重定向用于改变命令的输出。输出重定向更为常用,它经常用于将命令的结果输入到文件中,而不是屏幕上。输入重定向的命令是<,输出重定向的命令是>,另外还有错误重定向2>,以及追加重定向>>。
command > file :输出保存到file,覆盖file中原内容 类似tee
command >> file :追加,不覆盖

6、正则表达式RE(regular expression)

正则表达式主要用于搜寻字符串,匹配文件内容和过滤特殊信息等;具有十分强大的功能
在linux中常用的工具有grep, sed, awk

下面介绍几种简单的RE语法:

  • ^word :搜索字符在行首 ^[a-w]
  • word$ :搜索字符在行尾
  • . :任何一个可能的字符
  • \ :转义字符,将特殊字符变成普通字符
  • ? :任何一个单一字符
  • * : 重复匹配,一个或多个任意字符
  • [ ] :代表范围或列表 [0-9]

grep:
grep命令是Linux系统中一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。
参数:主要作用为设置输出方式

  • -c :打印符合要求的行数
  • -i :忽略大小写
  • -n :在输出符合要求的行的同时连同行号一起输出
  • -v :打印不符合要求的行
  • -A :后跟一个数字(有无空格都可以),例如 –A2则表示打印符合要求的行以及下面两行
  • -B :后跟一个数字,例如 –B2 则表示打印符合要求的行以及上面两行
  • -C :后跟一个数字,例如 –C2 则表示打印符合要求的行以及上下各两行

参数可以不用,直接进行re匹配,输出匹配结果
ex:
ubuntu@ubuntu:~/Documents$ grep -n ^”reboot” test2.text
带行号输出以reboot开头的在文件test2.text中的行内容

ubuntu@ubuntu:~/Documents$ grep -n [0-9] test2.text
带行号输出所有包含数字的行

ubuntu@ubuntu:~/Documents$ grep -n .*/6 test2.text
带行号输出具有格式 xxxx/6的行,x代表任意字符,个数不限

sed,awk
grep实现的只是查找功能,不能实现把查找的内容替换掉。sed工具以及下面要讲的awk工具就能实现把替换的文本输出到屏幕上的功能了,而且还有其他更丰富的功能。sed和awk都是流式编辑器,是针对文档的行来操作的。其内容较为复杂丰富,这里不再详细介绍

7、通配符

通配符是一种特殊语句,主要有* 和?两个符号:

*:一个或多个任意字符
?:一个任意字符

在寻找文件或目录名时,可以通过使用通配符来进行匹配查找相关的文件
ex:
ubuntu@ubuntu:~/Documents lstest?.texttest?.textubuntu@ubuntu: /Documents ls test*
列出以test为开头的文件或目录

8、shell脚本

shell脚本就是一些命令的集合

举个例子,我想实现这样的操作:1)进入到/tmp/目录;2)列出当前目录中所有的文件名;3)把所有当前的文件拷贝到/root/目录下;4)删除当前目录下所有的文件。简单的4步在shell窗口中需要你敲4次命令,按4次回车。这样是不是很麻烦?当然这4步操作非常简单,如果是更加复杂的命令设置需要几十次操作呢?那样的话一次一次敲键盘会很麻烦。所以不妨把所有的操作都记录到一个文档中,然后去调用文档中的命令,这样一步操作就可以完成。其实这个文档呢就是shell脚本了,只是这个shell脚本有它特殊的格式。

Shell脚本能帮助我们很方便的去管理服务器,因为我们可以指定一个任务计划定时去执行某一个shell脚本实现我们想要需求。这对于linux系统管理员来说是一件非常值得自豪的事情。现在的139邮箱很好用,发邮件的同时还可以发一条邮件通知的短信给用户,利用这点,我们就可以在我们的linux服务器上部署监控的shell脚本,比如网卡流量有异常了或者服务器web服务器停止了就可以发一封邮件给管理员,同时发送给管理员一个报警短信这样可以让我们及时的知道服务器出问题了。

调试sh
sh [-vnx] filename

  • -n 不执行脚本,检查语法
  • -v 执行前,先输出脚本内容
  • -x 将使用到的脚本显示

符号和语法:

第一行一般注明脚本程序目录,及运行脚本程序目录,就像python中的#!/usr/bin/python,这里是#!/bin/bash

单引号 ' ': 引号之间的字符均为普通字符,特殊字符也会失去原有意义
双引号" " 基本与单引号相同,但不忽略 $,\ ``三个特殊字符的用途,即双引号中遇到这三个特殊字符,它会解释特殊字符的意义,而单引号不会
反引号`` 反引号之中的字符被shell解释为命令行,即执行时,shell先执行反引号之间的命令,然后让返回结果代替反引号内容

# 表示注释

变量与=之间不能有空格,使用变量是要在变量前加$符号,shell中变量默认欸字符串。

在bash文件中:
ex:脚本文件名为hello.bash

$0代表脚本文件名称;$1代表输入参数1$2代表输入参数2echo $0
echo "the first parameter $1"    
echo "the first parameter $2"
echo "the first parameter $3"

运行:ubuntu@ubuntu:~/Documents/shfile$ sh hellp.sh ah bh ch
结果:

hellp.sh
the first parameter ah
the first parameter bh
the first parameter ch

declare:定义变量

  • -a定义为数组
  • -f定义为函数
  • -i定义为整数
  • -r定义为只读

ex:

ubuntu@ubuntu:~/Documents/shfile$ declare -i a=3
ubuntu@ubuntu:~/Documents/shfile$ declare -i b=5
ubuntu@ubuntu:~/Documents/shfile$ declare -i c=$a*$b
ubuntu@ubuntu:~/Documents/shfile$ echo $c
15

read:从外面获取参数

用来与用户进行交互
ex: read x 运行时可以从外面输入x的值,x被当作变量使用

空格的与否(重要)

  • 在写if条件判断的时候,要注意if后面需要空格
  • “ [ ” 后面 和“ ] ”前面都需要有空格。有没有感觉很无语。
  • 在shell脚本中当使用“ = ”给变量赋值的时候,在 “ = ”两边一定不能加空格,否者会把变量名当作一个命令来执行而报出“ command not found ”的错误
  • 在if条件判断的时候,if [ “判断条件” ] 判断条件中需要用到比较的时候则“ = ” 或者 ” != “的两边都需要用空格隔开。
  • 另外在写if判断的时候,不要忘记then,否者也会有问题。当然elif(相当于else if)是可选的。

运算符和逻辑比较

字符串的比较符号:

str1 = str2,字符串1匹配字符串2
str1 != str2,字符串1不匹配字符串2
str1 > str2,字符串1大于字符串2
str1 < str2,字符串1小于字符串2
-n str,字符串不为null,长度大于零
-z str,字符串为null,长度为零

数值大小比较不能用< = > 需要用下面的比较符:

-lt,小于
-le,小于等于
-eq,等于
-ge,大于等于
-gt,大于
-ne,不等于

文件属性比较

-d file :file存在并是一个目录
-e file :file 存在
-f file :file 存在并且是一个常规的文件(不是目录或者其他特殊类型文件)
-r file :有读的权限
-s file :文件存在且不为空
-w file :有写的权限
-x file :有执行的权限,或者对于目录有search的权限
-N file :在上次读取后,文件有改动
-O file :own所属的文件
-G file :group所属的文件
file1 -nt file2 :file1 比 file2 更新,以最后更新时间为准
file1 -ot file2 :file1 比 file2 更旧 ,以最后更新时间为准
#文件名是字符串,在脚本中使用时需要“”

括号使用及以上语法更加详细的说明参考:http://www.cnblogs.com/include/archive/2011/12/09/2307905.html

if-then-else语句

if [condition]; then
    statements
else
    statements
fi

ex:

#!bin/bash
#this to test the if language
#ubuntu

echo $0
echo "Press y to continue:"
read yn
if [ "$yn" = "y" ]||[ "$yn" = "Y" ];then
        echo "script is running..."
else
        echo "STOP!"
fi

echo "cin a number 0-100:"
read nb
if [ $nb -lt 60 ] ; then
        echo "not pass"
else
        echo "pass"
fi

if [ -e "iftest.sh" ] && [ -d "/home/ubuntu/Documents/shfile/" ]; then
        echo "file test pass"
else
        echo "test failed!"
fi

case:

选择语法,根据输入选择对应的操作;语法形式:

case value in
  value1)
      command
      ;;
  value2)
      command
     ;;
  *)
      command
      ;;
esac

ex1:

#!/bin/bash
#test case
#ubuntu
#2015/11/19
echo "the program is to test case!"
echo "Please input your choice{one/two/three} :"
read ch
case $ch in
  one)
        echo "your choice is one!"
        ;;
  two)
        echo "your choice is two!"
        ;;
  three)
        echo "your choice is three!"
        ;;
  *)
        echo "choice: one/two/three"
        ;;
esac

ex2:

#!/bin/bash
#test for case
#ubuntu
#2015/11/19
echo "the program will print your choice!"
case $1 in
  one)
        echo "your choice is one!"
        ;;
  two)
        echo "your choice is two!"
        ;;
  three)
        echo "your choice is three!"
        ;;
  *)
        echo "choice:one/two/three "
        ;;
esac

脚本这一块内容较为丰富复杂,这里只是作一简单了解,对于其准确的语法和数据结构等相关内容不作深入学习,有兴趣可以参考相关书籍。

你可能感兴趣的:(shell,脚本,ubuntu)