基础正则表达式
- 通配符
匹配符合条件的文件名,完全匹配;ls
、find
、cp
这些命令不支持正则就用通配符匹配 - 正则表达式
匹配文件中的字符串,包含匹配;grep
、awk
、sed
这些命令支持正则表达式
元字符 | 作用 |
---|---|
* | 前一个字符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: shenchao@lampbrother.net)
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"