linux_shell编程

基础正则表达式

  • 通配符
    匹配符合条件的文件名,完全匹配;lsfindcp这些命令不支持正则就用通配符匹配
  • 正则表达式
    匹配文件中的字符串,包含匹配;grepawksed这些命令支持正则表达式
元字符 作用
* 前一个字符0次或任意多次
. 匹配除换行符外任意一个字符
^ 匹配行首
$ 匹配行尾
[] 匹配中括号中任意一个字符
[^] 匹配中括号中字符以外的任意字符
\ 转义符
{n} 表示前面字符恰好出现n次
{n,} 前面字符出现不小于n次
{n,m} 表示前面字符至少出现n次,至多出现m次

字符截取命令

cut字段提取命令

grep命令可以提取行,cut可以提取列;文件需由制表符组成。cut命令通常和grep命令结合使用,通过管道符,依次实现功能

用法: cut [选项] 文件
选项:-f列号,提取第几列;-d分隔符,提取指定分隔符分割列(默认分隔符为制表符)

实例:提取当前系统所有非root用户

$ cat /etc/passwd|grep /bin/bash|grep -v root|cut -d ":" -f 1
# 查看所有用户信息,寻找正常用户信息,取反剔除root|取得第一列用户名信息

printf命令格式化打印(awk基础)

$ printf '输出类型输出格式' 输出格式
符号 作用
%ns 输出字符串。n是数字指代输出几个字符
%ni 输出整数。n是数字指代输出几个数字
%m.nf 输出浮点数。m和n是数字,指代输出的整数位数和小数位数

输出类型:

符号 作用
%ns 输出字符串。n是数字指代输出几个字符
%ni 输出整数。n是数字指代输出几个数字
%m.nf 输出浮点数。m和n是数字,指代输出的整数位数和小数位数
符号 作用
\a 输出警告音
\b 输出退格键,也就是Backspace
\f 清楚屏幕
\n 换行
\r 回车,也就是Enter键
\t 水平输出退格键,也就是Tab键
\v 垂直输出退格键,也就是Tab键

输出格式:

符号 作用
\a 输出警告音
\b 输出退格键,也就是Backspace
\f 清楚屏幕
\n 换行
\r 回车,也就是Enter键
\t 水平输出退格键,也就是Tab键
\v 垂直输出退格键,也就是Tab键

在awk命令中输出支持print和printf

  • print命令在输出之后自动加一个换行符
  • printf命令是标准输出,如果需要换行,就要添加换行符

实例:

$ vim stu.md
name    age     scole
john    12      88
alex    13      89
mei     12      90

$ printf '%s\t%s\t%s\t\n' $(cat stu.md)
name    age     scole
john    12      88
alex    13      89
mei     12      90

awk命令(强化的cut)

cut命令针对标准的确定的分隔符; awk先读入第一行,再使用$n截取第n列

命令:$ awk '条件1{动作1} 条件2{动作2}... 文件名

  • $ awk '$3>=88 {print $1}' stu.md
    条件判断,在第三列大于等于88时,打印对应第一列的内容(但是列表第一行为表头没有数字)
  • cat stu.md|grep -v name|awk '$3>=89 {print $1}'
    作用同上,提前反选出表头行
  • $ df -h|grep sda6|awk '{printf $5}'|cut -d "%" -f 1
    截取硬盘使用情况,选取sda6行,打印出第5列,截取百分号前的数字
  • $ awk 'BEGIN{print "test !!"} END{print "the end !!"} {print $2 "\t" $5}' stu.md
    在awk执行命令前后添加信息,执行一个额外的命令
  • 如果手工定义分隔符,一定要注意第一行,强制读入第一行
    $ awk '{FS=":"} {print $1} "\t" $3' /etc/passwd
    此时需强制使用“BEGIN”
    $ awk 'BEGIN{FS=":"} {print $1} "\t" $3' /etc/passwd

sed命令

sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。(可以从管道符收集数据修改)

命令:
$ sed [选项] '[动作]' 文件名

选项 作用
-n 一般sed命令会把所有数据都输出到屏幕 ,如果加入此选择,则只会把经过sed命令处理的行输出到屏幕。
-e 允许对输入数据应用多条sed命令编辑
-i 用sed的修改结果直接修改读件,而不是由屏幕输出

选项:

选项 作用
-n 一般sed命令会把所有数据都输出到屏幕 ,如果加入此选择,则只会把经过sed命令处理的行输出到屏幕。
-e 允许对输入数据应用多条sed命令编辑
-i 用sed的修改结果直接修改读件,而不是由屏幕输出
动作 作用
a\ 追加,在当前行后添加一行或多行。添加多行时,除最后 一行外,每行末尾需要用“\”代表数据未完结。
c\ 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结。
i\ 插入,在当期行前插入一行或多行。插入多行时,除最后 一行外,每行末尾需要用“\”代表数据未完结。
d 删除,删除指定的行。
p 打印,输出指定的行。
s 字串替换,用一个字符串替换另外一个字符串。格式为“行范围s/旧字串/新字串/g”(和vim中的替换格式类似) 。

动作:

动作 作用
a\ 追加,在当前行后添加一行或多行。添加多行时,除最后 一行外,每行末尾需要用“\”代表数据未完结。
c\ 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结。
i\ 插入,在当期行前插入一行或多行。插入多行时,除最后 一行外,每行末尾需要用“\”代表数据未完结。
d 删除,删除指定的行。
p 打印,输出指定的行。
s 字串替换,用一个字符串替换另外一个字符串。格式为“行范围s/旧字串/新字串/g”(和vim中的替换格式类似) 。

字符处理命令

排序命令sort:

$ sort [选项] 文件名

选项 作用
-f 忽略大小写
-n 以数值型进行排序,默认使用字符串型排序
-r 反向排序
-t 指定分隔符,默认是分隔符是制表符
-k n[,m] 按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)

实例:

  • $ sort -n -t ":" -k 3,3 /etc/passwd
    以“:”为分隔符,按照第三个字段的数字顺序排序

统计命令wc:

$ wc [选项] 文件名

选项 作用
-l 只统计行数
-w 只统计单词
-m 只统计字符

条件判断

按照文件类型进行判断

判断两种格式:

  • 方法1-命令格式: $ test -e /root/install.log
  • 方法2- 脚本格式:[$ -e /root/install.log ]
选项 作用
-b 文件 判断该文件是否存在,并且是否为块设备文件(是块设备文件为真)
-c 文件 判断该文件是否存在,并且是否为字符设备文件(是字符设备文件为真)
-d 文件 判断该文件是否存在,并且是否为目录文件(是目录为真)
-e 文件 判断该文件是否存在(存在为真)
-f 文件 判断该文件是否存在,并且是否为普通文件(是普通文件为真)
-L 文件 判断该文件是否存在,并且是否为符号链接文件(是符号链接文件为真)
-p 文件 判断该文件是否存在,并且是否为管道文件(是管道文件为真)
-s 文件 判断该文件是否存在,并且是否为非空(非空为真)
-S 文件 判断该文件是否存在,并且是否为套接字文件(是套接字文件为真)

加强判断:
[ -d /root ] && echo "yes" || echo "no"
判断文件目录是否存在,如果存在输出“yes”,如果不存在输出“no”

判断文件的读写权限

选项 作用
-r 文件 判断该文件是否存在,并且是否该文件拥有读权限(有读权限为真)
-w 文件 判断该文件是否存在,并且是否该文件拥有写权限(有写权限为真)
-x 文件 判断该文件是否存在,并且是否该文件拥有执行权限(有执行权限为真)
-u 文件 判断该文件是否存在,并且是否该文件拥有SUID权限(有SUID权限为真)
-g 文件 判断该文件是否存在,并且是否该文件拥有SGID权限(有SGID权限为真)
-k 文件 判断该文件是否存在,并且是否该文件拥有SBit权限(有SBit权限为真)

加强判断:
[ -w student.txt ] && echo "yes" || echo "no"
判断文件读写权限,如果具备写入权限,则输出“yes”,如果不存在则输出“no”

两个文件之间的判断

选项 作用
文件1 -nt 文件2(newer than) 判断文件1的修改时间是否比文件2的新(如果新则为真)
文件1 -ot 文件2(older than) 判断文件1的修改时间是否比文件2的旧(如果旧则为真)
文件1 -ef 文件2 判断文件1是否和文件2的Inode号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法

两个整数之间的判断

选项 作用
整数1 -eq 整数2(equal than) 判断整数1是否和整数2相等(相等为真)
整数1 -ne 整数2(no equal) 判断整数1是否和整数2不相等(不相等位置)
整数1 -gt 整数2(greater than) 判断整数1是否大于整数2(大于为真)
整数1 -lt 整数2(less than) 判断整数1是否小于整数2(小于位置)
整数1 -ge 整数2(greater or equal) 判断整数1是否大于等于整数2(大于等于为真)
整数2 -le 整数2(less or equal) 判断整数1是否小于等于整数2(小于等于为真)

实例:

$ [ 11 -gt 10 ] && echo "yes" || echo "no"
yes

字符串之间的判断

选项 作用
-z 字符串 判断字符串是否为空(为空返回真)
-n 字符串 判断字符串是否为非空(非空返回真)
字符串1 == 字符串2 判断字符串1是否和字符串2相等(相等返回真)
字符串2 !== 字符串2 判断字符串1是否和字符串2不相等(不相等返回真)

实例:

$ name=hello
$ [ -z "$name" ] && echo "yes" || echo "no"
no

多重条件判断

选项 作用
判断1 -a 判断2(and) 逻辑与,判断1和判断2都成立,最终的结果才为真
判断1 -o 判断2(or) 逻辑或,判断1和判断2有一个成立,最终的结果就为真
! 判断 逻辑非,使原始的判断式取反

实例:

$ aa=11
$ [ -n "$aa" -a "$aa" -gt 12 ] && echo "yes" || echo "no"
# “-n”判断变量aa是否存在,同时判断变量aa是否大于12

流程控制

if语句

if [ 条件判断式 ]; then
    程序
fi

或者

if [ 条件判断式 ]
    then
        程序
fi

双分支if条件句

if [ 条件判断式 ]
    then
        条件成立时,执行的程序
    else
        条件不成立时,执行的程序
fi

实例1:

#!/bin/bash
#coding:utf-8
#统计根分区使用率
#Author: alex

rate=$(df -h | grep "/dev/sda1" | awk '{print $5}' | cut -d "%" -f 1)
# 将根分区使用率赋值给变量rate

if [ $rate -ge 80 ]
    then
        echo "Warning! /dev/sda1 is full!!"
    else
    echo "/dev/sda1 is fine!" 
fi

实例2:

#!/bin/bash
# Author: shenchao (E-mail: [email protected])

port=$(nmap -sT 192.168.10.1 | grep tcp | grep http | awk '{print$2}')
#使用nmap命令扫描服务器,并截取apache服务的状态,赋予变量port
if [ "$port" == "open" ]
    then
        echo “$(date) httpd is ok!” >> /tmp/autostart-acc.log
    else
        /etc/rc.d/init.d/httpd start &>/dev/null
        echo "$(date) restart httpd !!" >> /tmp/autostart-err.log
fi

nmap命令

$ nmap -sT 192.168.10.1

Starting Nmap 7.01 ( https://nmap.org ) at 2017-08-22 18:15 CST
Nmap scan report for 192.168.10.1
Host is up (0.018s latency).
Not shown: 997 filtered ports
PORT     STATE SERVICE
80/tcp   open  http
1900/tcp open  upnp
9876/tcp open  sd
MAC Address: 30:B4:9E:4C:83:70 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 4.78 seconds

多分支if条件句

if [ 条件判断式1 ]
    then
        条件判断式1为真,执行程序1
elif [ 条件判断式2 ]
    then
    条件判断式2为真,执行程序2
...
else
    程序
fi

实例:

#!/bin/bash
#判断用户输入的是什么条件,针对于当前目录文件和目录
#Author:alex

read -p "PLease input a filename:" file
#接收键盘的输入,并赋予变量file

if [ -z "$file" ]
#判断file是否存在
    then
        echo "Error, please input a filename!"
        exit 1
elif [ ! -e "$file" ]
#判断file的值是否存在
    then
        echo "Your input is not a file!"
elif [ -f "$file" ]
#判断file的值是否为普通文件
    then
        echo "$file is a regulare file!"
elif [ -d "$file" ]
#判断file的值是否为目录文件
    then
        echo "$file is a directory!"
else
    echo "$file is an other file!"
fi
   

case语句

case语句和if...elif...else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。

语法:

case $变量名 in
    “值1”)
        echo “Your choose is yes!”
        ;;
    "no")
        echo "Your choose is no!"
        ;;
    ...snip...
    *)
        如果变量的值都不是以上的值,则执行此程序
        ;;
esac

实例:

#!/bin/bash
# test case
#Author:alex

echo "if you are male, enter M"
echo "if you are female, enter F"

read -t 30 -p "what is your gender: " gender

case $gender in
        "M")
                echo "Male"
                ;;
        "F")
                echo "Female"
                ;;
        *)
                echo "error M/F"
                ;;
esac

for循环

语法1:

for 变量 in 值1 值2 值3 ...
    do
        程序
    done
  • 实例1:
#!/bin/bash
# test for
#Author:alex

for time in yesterday today tomorrow
        do
                echo "it is $time!"
        done

  • 实例2:

语法2:

for((初始值;循环控制条件;变量变化))
    do
        程序
    done
  • 实例1:
#!/bin/bash
# 高斯,1加到100
#Author:alex

s=0
for ((i=1;i<=100;i=i+1))
        do
                s=$(($s+$i))
        done
        echo "the sum of 1+2+...100 is:$s"
  • 实例2:
#!/bin/bash

read -t 30 -p "add user_name: " name
read -t 30 -p "add user_num: " num
read -t 30 -p "add passwd:" pass

if [ ! -z "$name" -a ! -z "$num" -a ! -z "$pass" ]
        then
                y=$(echo $num | sed 's/^[0-9]*$'//g)
                if [ -z "$y" ]
                        then
                        for ((i=1;i<=$num;i=i+1))
                                do
                                        sudo useradd $name$i &>/dev/null
                                        echo $pass | sudo passwd --stdin $name$i &>/dev/null
                                done
                fi
fi

  • 实例3:
#!/bin/bash
# 删除新添加的用户
#Author:alex

new_users=$(tail /etc/passwd | grep '/home' | awk 'BEGIN{FS=":"}{print $1}'|grep -v "alex")

for user in $new_users
        do
                userdel $user &> /dev/null
        done

while循环

while循环是不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这和for的固定循环不一样。

语法:

while [条件判断式]
    do
        程序
    done

实例:

#!/bin/bash
# test while
# Author: alex

i=1
s=0
while [ "$i" -le 100 ]
        do
                s=$(($s+$i))
                i=$(($i+1))
        done
echo "the sum is: $s"

until 循环是一个终止条件循环

语法:

while [条件判断式]    # t当满足此条件时执行以下循环
    do
        程序
    done

实例:

#!/bin/bash
# test while
# Author: alex

i=1
s=0
until [ "$i" -gt 100 ]    #执行以下操作,直到不满足该条件时停止
        do
                s=$(($s+$i))
                i=$(($i+1))
        done
echo "the sum is: $s"

你可能感兴趣的:(linux_shell编程)