文本处理工具

文件查看

文件查看命令

···
cat,nl,tac,rev
cat [OPTION]... [FILE]... -E:显示行结束符$
-n:对显示出的每一行进行编号

-A:显示所有控制符
-b:非空行编号
-s:压缩连续的空行成一行
nl
tac
rev

查看非文本文件内容

hexdump:以16进制查看文本
hexdump -C -n 512 /dev/sda  
00000000 eb 63 90 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0 |.c..............|  
echo {a..z} | tr -d ' '|hexdump -C  
00000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 
xxd  
echo {a..z} | tr -d ' '|xxd  
0000000: 6162 6364 6566 6768 696a 6b6c 6d6e 6f70 abcdefghijklmnop  
0000010: 7172 7374 7576 7778 797a 0a  qrstuvwxyz.    

分页查看文件内容

more:分页查看文件  
   more [OPTIONS...]FILE...  
-d: 显示翻页及退出提示  
less:一页一页地查看文件或STDIN输出  
查看时有用的命令包括:  
/文本 搜索 文本  
n/N 跳到下一个 或 上一个匹配  
less 命令是man命令使用的分页器  

显示文本前或后行内容

head [OPTION]... [FILE]...  
-c # 指定获取前#字节  
-n # 指定获取前#行  
-# 同上  
tail [OPTION]... [FILE]...  
-c # 指定获取后#字节  
-n # 指定获取后#行  
-# 同上  
-f 跟踪显示文件fd新追加的内容,常用日志监控相当 --follow=descriptor  
-F 跟踪文件名,相当于--follow=name --retry  
tailf 类似tail –f,当文件不增长时并不访问文件  

按列抽取文本cut和合并文件paste

cut [OPTION]... [FILE]...  
-d DELIMITER: 指明分隔符,默认tab  
-f FILEDS:  
  #: 第#个字段  
  #,#[,#]:离散的多个字段,例如1,3,6  
  #-#:连续的多个字段, 例如1-6  
   混合使用:1-3,7  
-c 按字符切割  
--output-delimiter=STRING指定输出分隔符  

cut和paste

显示文件或STDIN数据的指定列  
cut -d: -f1 /etc/passwd  
cat /etc/passwd | cut -d: -f7  
 cut -c2-5 /usr/share/dict/words  
paste 合并两个文件同行号的列到一行  
paste [OPTION]... [FILE]...  
-d 分隔符:指定分隔符,默认用TAB  
 -s : 所有行合成一行显示  
 示例:  
paste f1 f2  
paste -s f1 f2  

分析文本的工具

文本数据统计:wc  
整理文本:sort  
比较文件:diff和patch  
  
收集文本统计数据wc  
可用于统计文件的行总数、单词总数、字节总数和字符总数  
可以对文件或STDIN中的数据统计  
wc story.txt  
39 237 1901 story.txt  
行数 字数 字节数  
常用选项  
-l 只计数行数  
-w 只计数单词总数  
-c 只计数字节总数  
-m只计数字符总数  
-L 显示文件中最长行的长度  
  
文本排序sort  
把整理过的文本显示在STDOUT,不改变原始文件  
sort [options] file(s)  
常用选项  
-r 执行反方向(由上至下)整理  
-R 随机排序  
-n 执行按数字大小整理  
-f 选项忽略(fold)字符串中的字符大小写  
-u 选项(独特,unique)删除输出中的重复行  
-t c 选项使用c做为字段界定符  
-k X 选项按照使用c字符分隔的X列来整理能够使用多次  

uniq  
uniq命令:从输入中删除前后相接的重复的行  
uniq [OPTION]... [FILE]...  
-c: 显示每行重复出现的次数  
-d: 仅显示重复过的行  
-u: 仅显示不曾重复的行  
 注:连续且完全相同方为重复  
常和sort 命令一起配合使用:  
 sort userlist.txt | uniq -c  
  
比较文件  
比较两个文件之间的区别  
diff foo.conf foo2.conf  
5c5  
< use_widgets = no   
---  
> use_widgets = yes  
注明第5行有区别(改变)  

复制对文件改变patch  
diff 命令的输出被保存在一种叫做“补丁”的文件中  
使用 -u 选项来输出“统一的(unified)”diff格式文件,最适用于补丁文件  
patch 复制在其它文件中进行的改变(要谨慎使用)  
适用 -b 选项来自动备份改变了的文件  
diff -u foo.conf foo2.conf > foo.patch  
patch -b foo.conf foo.patch  

grep

grep: Global search REgular expression and Print out the line  
作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行  
模式:由正则表达式字符及文本字符所编写的过滤条件  
grep [OPTIONS] PATTERN [FILE...]  
grep root /etc/passwd  
grep "$USER" /etc/passwd  
grep '$USER' /etc/passwd  
 grep `whoami` /etc/passwd  
 grep命令选项  
 --color=auto: 对匹配到的文本着色显示  
 -m # 匹配#次后停止  
 -v 显示不被pattern匹配到的行  
 -i 忽略字符大小写  
 -n 显示匹配的行号  
 -c 统计匹配的行数  
 -o 仅显示匹配到的字符串  
 -q 静默模式,不输出任何信息  
 -A # after, 后#行  
 -B # before, 前#行  
 -C # context, 前后各#行  
 -e 实现多个选项间的逻辑or关系  
grep –e ‘cat ’ -e ‘dog’ file  
 -w 匹配整个单词  
 -E 使用ERE  
 -F 相当于fgrep,不支持正则表达式  
 -f file 根据模式文件处理  

正则表达式

分两类:  
基本正则表达式:BRE  
扩展正则表达式:ERE  
grep -E, egrep  
正则表达式引擎:  
采用不同算法,检查处理正则表达式的软件模块  
 PCRE(Perl Compatible Regular Expressions)  
元字符分类:字符匹配、匹配次数、位置锚定、分组  
man 7 regex  
基本正则表达式元字符  
字符匹配:  
. 匹配任意单个字符  
[] 匹配指定范围内的任意单个字符,  示例:[wang] [0-9] [a-z] [a-zA-Z]  
[^] 匹配指定范围外的任意单个字符  
[:alnum:] 字母和数字  
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z  
[:lower:] 小写字母 [:upper:] 大写字母  
[:blank:] 空白字符(空格和制表符)  
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)  
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)  
[:digit:] 十进制数字 [:xdigit:]十六进制数字  
[:graph:] 可打印的非空白字符  
[:print:] 可打印字符  
[:punct:] 标点符号  
  
匹配次数:  
用在要指定次数的字符后面,用于指定前面的字符要出现的次数  
* 匹配前面的字符任意次,包括0次  
贪婪模式:尽可能长的匹配  
.* 任意长度的任意字符  
\? 匹配其前面的字符0或1次  
\+ 匹配其前面的字符至少1次  
\{n\} 匹配前面的字符n次  
\{m,n\} 匹配前面的字符至少m次,至多n次  
\{,n\} 匹配前面的字符至多n次  
\{n,\} 匹配前面的字符至少n次  
  
位置锚定:  
定位出现的位置  
^ 行首锚定,用于模式的最左侧  
$ 行尾锚定,用于模式的最右侧  
^PATTERN$ 用于模式匹配整行  
^$ 空行  
^[[:space:]]*$ 空白行  
\< 或 \b 词首锚定,用于单词模式的左侧  
\> 或 \b 词尾锚定,用于单词模式的右侧  
\<PATTERN\> 匹配整个单词   
  
分组:  \(\) 将一个或多个字符捆绑在一起,当作一个整体处理,如:\(root\)\+  
分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些
变量的命名方式为: \1, \2, \3, ...  
\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符  
示例: \(string1\(string2\)\)  
 \1 :string1\(string2\)  
 \2 :string2  
后向引用:引用前面的分组括号中的模式所匹配字符,而非模式本身  
 示例:a\|b a或b   
 C\|cat C或cat   
 \(C\|c\)at Cat或cat  

扩展正则表达式

次数匹配:  
* 匹配前面字符任意次  
? 0或1次  
+ 1次或多次  
{m} 匹配m次  
{m,n} 至少m,至多n次  
位置锚定:  
^ 行首  
$ 行尾  
\<, \b 语首  
\>, \b 语尾  
分组:  
()  
后向引用:\1, \2, ...  
或者:  
a|b a或b  
C|cat C或cat  
(C|c)at Cat或cat  

shell脚本基础编程

程序

程序:算法加数据的结构
数据:是程序的核心
数据结构:数据在计算机中的类型和组织方式
算法:处理数据的方式
过程是:shell是过程是的的程序编码风格
以指令为中心,数据服务指令。
执行方式:解释执行
解释一行命令,执行一行。缺点有可能一个程序只执行一半,对脚本要求比较严格。
基本结构:各种系统命令的组合
数据存储:变量,数组
表达式:数据运算
格式:
语句:if

格式:首行shebang机制

#!/bin/bash    
shell脚本的用途:  
自动化常用命令:每天都要执行的的命令  就需要去做一个脚本,  
创建脚本:  
第一步:使用文本编辑器来创建一个文本文件  
第一行必须包括shell声序列:#!  
        #!/bin/bash  
添加注释:  
注释以#开头:  
脚本的用途-作者-名称-时间等等.....  
示例:写入 家目录下的.vimrc如果没有需自己创建  
写入:.vimrc.note  

第二部:运行脚本  
给予执行权限,在命令行上指定脚本的绝对或相对路径.file.sh(或者在变量$PASH中/etc/profile.d/env.sh中  写入PATH=/file.sh的目录名:$PATH)  
直接运行解释器,将脚本作为解释器程序的参数运行  

脚本规范

脚本代码开头约定  
1、第一行一般为调用使用的语言  
2、程序名,避免更改文件名为无法找到正确的文件  
3、版本号  
4、更改后的时间  
5、作者相关信息  
6、该程序的作用,及注意事项  
7、最后是各版本的更新简要说明  

脚本调试:

检测脚本中的语法错误:  
bash -n /file.sh  检查语法错误 不执行脚本 命令错误检查不出来  
调试执行:  
bash -x /file.sh 看到每条命令执行的结果 执行命令  
变量  

Shell中变量命名法则:

1、不能使程序中的保留字:例如if, for  
2、只能使用数字、字母及下划线,且不能以数字开头  
3、见名知义  
4、统一命名规则:驼峰命名法  单词都首字母大写  
Shell中命名建议规则:  
1、变量名大写  
2、局部变量小写  
3、函数名小写  
4、用英文名字,并体现出实际作用  

变量种类

局部变量:只在当前shell进程中生效  
环境变量:当前shell和其子shell进程中生效  
位置变量:$1, $2, ...来表示,用于让脚本在脚本代码中调用通过命令行传  
递给它的参数  
局部变量:   
变量赋值:name=“value”  
可以使用引用value  
(1)可以是直接字串:name=“root”  
(2)变量引用:name=“$USER”  
(3)命令引用:name=`COMMAND`  
name=$(COMMAND)  
变量引用:${name}或者$name  
" " 		弱引用,其中的变量引用会被替换为变量值  

' ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串  
显示已定义的所有变量:set  
删除变量:unset name  
pstree   查看进程树  

练习
1、编写脚本 systeminfo.sh,显示当前主机系统信息,包括主机名,IPv4地址, 操作系统版本,内核版本,CPU型号,内存大小,硬盘大小 #!/bin/bash
COLOR="\033[1;35m"
COLOREND="\033[0m"
echo -e "cup name:${COLOR}cat /proc/cpuinfo |grep "model name"|cut -d: -f2$COLOREND"
echo -e "memory Size:${COLOR}cat /proc/meminfo |head -1|cut -d: -f2$COLOREND"
echo -e "disk Size: ${COLOR}cat /proc/partitions |grep -w sda|tr -s ' '|cut -d' ' -f4 kB$COLOREND"
echo -e "system number:${COLOR}cat /etc/redhat-release$COLOREND"
echo -e "kernel: ${COLOR}uname -r$COLOREND"
echo -e "hostname: ${COLOR}hostname$COLOREND"
echo -e "who is login:${COLOR}who$COLOREND"
echo -e "who am i:${COLOR}whoami$COLOREND"

2、编写脚本 backup.sh,可实现每日将/etc/目录备份到/backup/etcYYYYmm-dd中 #!/bin/bash
COLOR="\033[1;35m"
COLOREND="\033[0m"
echo -e "${COLOR}To start backup$COLOREND"
TIME="date +"%F_%T""
mkdir /data/backup/etc$TIME
cp -a /etc /data/backup/etc$TIME
echo -e "${COLOR}backup end$COLOREND"

3、编写脚本 disk.sh,显示当前硬盘分区中空间利用率最大的值 #!/bin/bash
COLOR="\033[1;35m"
COLOREND="\033[0m"
echo -e "${COLOR}df |grep /dev/sd|tr -s ' '|cut -d' ' -f 5|sort -nr|head -1$C OLORE
4、编写脚本 links.sh,显示正连接本主机的每个远程主机的IPv4地址和连接数, 并按连接数从大到小排序[0-9] [1-9][0-9] 1[0-9][0-9] 2[0-4][0-9] 25[0-5] [root@ldap data]# netstat -ntu|grep ESTABLISHED|tr -s '' :| netstat -ntu|grep ESTABLISHED|tr -s ' ' :|cut -d: -f6 192.168.38.1

###正则回顾:.表示一个任意字符

  • 前面字符重复零次或零次以上
    [wang] 表示括号里的某一个
    [.?] 放在中括号里的符号就是他本身 没有其他含义
    [^0-9] 取反 或[^[:digit:]]
    ? 出现一次或者一次
    + 至少出现一次 一次以上
    {10} 出现10 次
    {10,20} 出现10次至20次之间
    ^[[::space:]]
    表示以空白符为行首的行
    $结尾的
    ^[[:digit:]]+$ 纯数字的行
    \bwang wang出现在单词的词首
    wang\b ……………………词尾
    \(内容\) 分组
    \1 \2 分组引用
    | a|bcd a 或bcd (a|b)cd 表示acd 或bcd

NAME="WANG YA KUN" 把带空格字符串的赋值给某个字符需加引号括起来
FILE=cat /ect/issue echo "$FILE" 显示命令或文件变量时 需括起来

环境变量

变量声明、赋值:  
name=VALUE  
export name=VALUE                                                             
在\etc\profile.d/env.sh中添加  
declare -x name=VALU               export  EDITOR=vim  
变量引用:                          后所有调用编辑器的命令会自动调用vim   
$name, ${name}  
显示所有环境变量:                 环境变量中 _存的是上一条命令的最后一个字符串  
env 常用                           $_  
printenv  
export  
declare -x  
删除变量:  
unset name  
只读位置变量:  
 readonly name  
declare -r name  
查看只读变量:  
readonly  -p   

位置变量:

在脚本代码中调用通过命令行传递给脚本的参数  
$1, $2, ... 对应第1、第2等参数,shift [n]换位置  $10 需加{10} {}变量界定 ${10}  
$0 命令本身  
$* 传递给脚本的所有参数,全部参数合为一个字符串  
$@ 传递给脚本的所有参数,每个参数为独立字符串  
$# 传递给脚本的参数的个数  
 注意:$@ $* 只在被双引号包起来的时候才会有差异  
set -- 清空所有位置变量  

退出状态

进程使用退出状态来报告成功或失败  
0 代表成功,1-255代表失败  
$? 变量保存最近的命令退出状态  
例如:  
ping -c1 -W1 hostdown &> /dev/null   
echo $?  

算术运算

bash中的算术运算:help let   
+, -, *, /, %取模(取余), **(乘方),乘法符号有些场景中需要转义  
实现算术运算:  
  (计算结果赋值到var)  
(1)let  var=算术表达式                        echo $RANDOM   生成随机数字  
(2) var=$[算术表达式]
(3) var=$((算术表达式))    只能用((存放被赋值的字符进行运算))   ((i++)) =i+1  
(4) var=$(expr arg1 arg2 arg3 ...)         
(5) declare –i var = 数值  
(6) echo ‘算术表达式’ | bc  
bash有内建的随机数生成器变量:$RANDOM(0-32767)  
示例:生成 0 - 49 之间随机数  
echo $[$RANDOM%50]  
赋值  
增强型赋值:  
+=, -=, *=, /=, %=         x=10  $[x+=2]  =12    x=x加2 在原数2  
let varOPERvalue         $[x/=4]  =2  只能去整数  
例如:let count+=3  
自加3后自赋值  
自增,自减:  
let var+=1  
let var++  
let var-=1  
let var--  

练习

1、编写脚本 sumid.sh,计算/etc/passwd文件中的第10个用户和第20用户的 UID之和

  #!/bin/bash  
  UNMBER1=`cat /etc/passwd |head -10|tail -1|cut -d: -f3`  
  UNMBER2=`cat /etc/passwd |head -20|tail -1|cut -d: -f3`  
  let naem=UNMBER1+UNMBER2  
  echo $naem        

2、编写脚本 sumspace.sh,传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和

unmber1=`grep ^$ $1|uniq -c`  
unmber2=`grep ^$ $2|uniq -c`  
let name=unmber1+unmber2      
echo $name    

3、编写脚本 sumfile.sh,统计/etc, /var, /usr 目录中共有多少个一级子目录和 文件

FILE1=`ls /etc/|wc -l`  
FILE2=`ls /var/|wc -l`  
FILE3=`ls /usr/|wc -l`                
name=$[FILE1+FILE2+FILE3]  
echo $name  

逻辑运算

非:!
! 1 = 0 ! true true专门返回成功
! 0 = 1 ! false false专门返回失败

短路运算

短路与
第一个为0,结果必定为0  
第一个为1,第二个必须要参与运算  
CMD1 && CMD2  
如果CMD1成功了,就执行CMD2  
如果CMD1失败了,就不执行CMD2  

####短路或

第一个为1,结果必定为1  
第一个为0,第二个必须要参与运算  
如果CMD1成功了,就不执行CMD2  
如果CMD1失败了,就执行CMD2  
异或:^
异或的两个值,相同为假,不同为真  
0^0  = 假0  
1^0  = 真1  
12^8
1 1 0 0     12                    0 1 0 0     4   
1 0 0 0      8                     1 0 0 0     8  
0 1 0 0       4                    1 1 0 0    12  
变量互换:  
x=12;y=8;tmp=$x;x=$y:y=$tmp;echo x=$x.y=$y  
异或:  
x=12;y=8;x=$[x^y];y=$[x^y]:x=$[x^y];echo $x,$y    

条件测试

判断某需求是否满足,需要由测试机制来实现  
 专用的测试表达式需要由测试命令辅助完成测试过程  
评估布尔声明,以便用在条件性执行中  
• 若真,则返回0  
• 若假,则返回1  

测试命令:

• test EXPRESSION       test是个内部命令和[ ]等价  
• [ EXPRESSION ]  
• [[ EXPRESSION ]]   支持正则表达式 示例:[[ "$file"=~ \.sh ]] 匹配$file是否为.sh 结尾  在用[[ ]]时$file最好加上双引号   [[ $flie== ]]  
 注意:EXPRESSION前后必须有空白字符  

bash的数值测试

-v VAR  
变量VAR是否设置  
数值测试:                           面试:   
-gt 是否大于      (;)把多个命令一起执行用;分开,需要小括号开启子shell变量只影响括号里  
-ge 是否大于等于             的,也可引用父进程的本地和环境变量  
-eq 是否等于  
-ne 是否不等于       {  } 把多个命令一起执行用;分开 在当前shell中   
-lt 是否小于  
-le 是否小于等于  

bash的字符串测试

字符串测试:                  示例:[[ "$file" =~  \.sh ]] 匹配$file是否为.sh 结尾  在用[[ ]]时  
> ascii码是否大于ascii码  $file最好加上双引号 只有=~后跟扩展正则  =~前后加空格  
= 是否等于                           
< 是否小于                           [[ “$flie” ==  *]]  =后跟的是通配符         
!= 是否不等于                          
=~ 左侧字符串是否能够被右侧的PATTERN所匹配   后面用扩展正则表达式  
 注意: 此表达式一般用于[[ ]]中;扩展的正则表达式  
 -z "STRING“ 字符串是否为空,空为真,不空为假   判断字符串是否为空的是或需加“  ”  
 -n "STRING“ 字符串是否不空,不空为真,空为假  
 注意:用于字符串比较时的用到的操作数都应该使用引号  

Bash的文件测试

存在性测试  
-a FILE:同 -e  
-e FILE: 文件存在性测试,存在为真,否则为假    示例   [ -e “$1" ]  
存在性及类别测试  
-b FILE:是否存在且为块设备文件  
-c FILE:是否存在且为字符设备文件  
-d FILE:是否存在且为目录文件  
-f FILE:是否存在且为普通文件  
-h FILE 或 -L FILE:存在且为符号链接文件  
-p FILE:是否存在且为命名管道文件  
-S FILE:是否存在且为套接字文件  
Bash的文件权限测试  

文件权限测试:

-r FILE:是否存在且可读  
-w FILE: 是否存在且可写  
-x FILE: 是否存在且可执行  
文件特殊权限测试:  
-u FILE:是否存在且拥有suid权限  
-g FILE:是否存在且拥有sgid权限  
-k FILE:是否存在且拥有sticky权限  

Bash的文件属性测试

文件大小测试:  
-s FILE: 是否存在且非空  
文件是否打开:  
-t fd: fd 文件描述符是否在某终端已经打开  
-N FILE:文件自从上一次被读取之后是否被修改过  
-O FILE:当前有效用户是否为文件属主  
-G FILE:当前有效用户是否为文件属组  
Bash的文件属性测试  
双目测试:  
FILE1 -ef FILE2: FILE1是否是FILE2的硬链接  
FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)  
FILE1 -ot FILE2: FILE1是否旧于FILE2  

Bash的组合测试条件

第一种方式:  
[ EXPRESSION1 -a EXPRESSION2 ] 并且  
[ EXPRESSION1 -o EXPRESSION2 ] 或者  
[ ! EXPRESSION ] 取反  
 -a 和 -o 需要使用测试命令进行,[[ ]] 不支持  
条件性的执行操作符  
示例:  
grep -q no_such_user /etc/passwd || echo 'No such user'   
No such user  
ping -c1 -W2 station1 &> /dev/null \       c是ping几次  
> && echo "station1 is up" \              W是超时几秒 W2两秒收不到 显示  ping不通  
> || (echo 'station1 is unreachable'; exit 1)   
station1 is up  
Bash的组合测试条件  
 示例:  
test "$A" = "$B" && echo "Strings are equal"   
test “$A”-eq “$B” && echo "Integers are equal“  
[ "$A" = "$B" ] && echo "Strings are equal"   
[ "$A" -eq "$B" ] && echo "Integers are equal“  
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab  
[ -z “$HOSTNAME” -o $HOSTNAME = "localhost.localdomain" ] \  
&& hostname www.magedu.com  

合法IP:

 [[ "$IP" =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]] && echo $IP is legal ip || echo $IP is illegal  ip  
(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])  

使用read命令来接受输入

使用read来把输入值分配给一个或多个shell变量    管道 | 是在管道后开一个字进程  
-p 指定要显示的提示          echo mage 30 | { read NAME AGE; echo $MAGE $AGE ; }  
-s 静默输入,一般用于密码    	mage    30  
-n N 指定输入的字符长度N  
-d ‘字符’ 输入结束符  
-t N TIMEOUT为N秒  
read 从标准输入中读取值,给每个单词分配一个变量  
所有剩余单词都被分配给最后一个变量  
read -p “Enter a filename: “ FILE  

条件选择if语句

选择执行:  
注意:if语句可嵌套  
单分支  
if 判断条件;then  
条件为真的分支代码  
fi  
双分支  
if 判断条件; then  
条件为真的分支代码  
else  
条件为假的分支代码  
fi  
if 语句  
多分支  
if 判断条件1; then  
条件1为真的分支代码  
elif 判断条件2; then  
条件2为真的分支代码  
elif 判断条件3; then  
条件3为真的分支代码  
else  
以上条件都为假的分支代码  
fi  
逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句  

if示例

根据命令的退出状态来执行命令  
if ping -c1 -W2 station1 &> /dev/null; then   
echo 'Station1 is UP'   
elif grep "station1" ~/maintenance.txt &> /dev/null; then   
echo 'Station1 is undergoing maintenance'  
else   
exit 1   
fi  

条件判断:case语句

case 变量引用 in  
PAT1)  
分支1  
;;  
PAT2)  
分支2  
;;  
...  
*)  
默认分支  
;;  
esac  
case支持glob风格的通配符:  
*: 任意长度任意字符  
?: 任意单个字符  
[]:指定范围内的任意单个字符  
a|b: a或b  

bash如何展开命令行

把命令行分成单个命令词  
展开别名  
展开大括号的声明({})  
展开波浪符声明(~)  
命令替换$() 和 ``)  
再次把命令行分成命令词  
展开文件通配(*、?、[abc]等等)  
准备I/0重导向(<、>)  
运行命令  
防止扩展  
反斜线(\)会使随后的字符按原意解释  
echo Your cost: \$5.00   
Your cost: $5.00  
加引号来防止扩展  
• 单引号(’’)防止所有扩展  
• 双引号(”“)也可防止扩展,但是以下情况例外:  
$(美元符号) 变量扩展    
` ` (反引号) 命令替换  
!(叹号) 历史命令替换  

bash的配置文件

按生效范围划分,存在两类:   
全局配置:     
/etc/profile  
/etc/profile.d/*.sh  
/etc/bashrc  
个人配置:  
~/.bash_profile  
~/.bashrc  

shell登录两种方式

交互式登录:  
(1)直接通过终端输入账号密码登录  
执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile -->   
~/.bashrc --> /etc/bashrc  
非交互式登录:   
(1)su UserName    
(2)图形界面下打开的终端   
(3)执行脚本  
(4)任何其它的bash实例  

执行顺序:

 /etc/profile.d/*.sh --> /etc/bashrc -->~/.bashrc  
Profile类  
按功能划分,存在两类:  
profile类和bashrc类  
profile类:为交互式登录的shell提供配置  
全局:/etc/profile, /etc/profile.d/*.sh  
个人:~/.bash_profile  
功用:  
(1) 用于定义环境变量  
(2) 运行命令或脚本  
Bashrc类  
bashrc类:为非交互式和交互式登录的shell提供配置  
全局:/etc/bashrc  
个人:~/.bashrc  
功用:  
(1) 定义命令别名和函数  
(2) 定义本地变量  
编辑配置文件生效  
修改profile和bashrc文件后需生效  
两种方法:  
1重新启动shell进程  
2 . 或source  
例:  
. ~/.bashrc  
Bash 退出任务  
保存在~/.bash_logout文件中(用户)  
在退出登录shell时运行  
用于  
• 创建自动备份  
• 清除临时文件  

set 命令

$- 变量  
h:hashall,打开这个选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭  
i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的  
shell。所谓的交互式shell,在脚本中,i选项是关闭的。  
m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等。    
H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完  
成,例如“!!”返回上最近的一个历史命令,“!n”返回第 n 个历史命令  

脚本安全

set 命令  
-u 在扩展一个没有设置的变量时,显示错误信息  
 等同set -o nounset  
-e 如果一个命令返回一个非0退出状态值(失败)就退出  
 等同set -o errexit  

文件查找和压缩

文件查找

在文件系统上查找符合条件的文件  
文件查找:locate, find  
非实时查找(数据库查找):locate  
实时查找:find  

locate

查询系统上预建的文件索引数据库  
/var/lib/mlocate/mlocate.db  
依赖于事先构建的索引  
 索引的构建是在系统较为空闲时自动进行(周期性任务),管理员手动更新数据库  
(updatedb)  
索引构建过程需要遍历整个根文件系统,极消耗资源  
工作特点:  
• 查找速度快  
• 模糊查找  
• 非实时查找  
• 搜索的是文件的全路径,不仅仅是文件名  
• 可能只搜索用户具备读取和执行权限的目录  

locate KEYWORD  
常用选项  
-i 不区分大小写的搜索  
-n N 只列举前N个匹配项目  
-r 使用基本正则表达式  
示例  
搜索名称或路径中带有“conf”的文件  
locate conf  
使用Regex来搜索以“.conf”结尾的文件  
locate -r ‘\.conf$  

find

语法:  
find [OPTION]... [查找路径] [查找条件] [处理动作]  
查找路径:指定具体目标路径;默认为当前目录  
查找条件:指定的查找标准,可以文件名、大小、类型、权限等标准进行;  
默认为找出指定路径下的所有文件  
处理动作:对符合条件的文件做操作,默认输出至屏  

查找条件
指搜索层级  
-maxdepth level 最大搜索目录深度,指定目录下的文件为第1级  
-mindepth level 最小搜索目录深度  
先处理目录内的文件,再处理指定目录
-depth  
根据文件名和inode查找:  
-name "文件名称":支持使用glob  
*, ?, [], [^]  
-iname "文件名称":不区分字母大小写  
-inum n 按inode号查找  
-samefile name 相同inode号的文件  
-links n 链接数为n的文件  
-regex “PATTERN”:以PATTERN匹配整个文件路径,而非文件名称  

根据属主、属组查找:  
-user USERNAME:查找属主为指定用户(UID)的文件  
-group GRPNAME: 查找属组为指定组(GID)的文件  
-uid UserID:查找属主为指定的UID号的文件  
-gid GroupID:查找属组为指定的GID号的文件  
-nouser:查找没有属主的文件  
-nogroup:查找没有属组的文件  
  
根据文件类型查找  
 -type TYPE  
• f: 普通文件  
• d: 目录文件  
• l: 符号链接文件  
• s:套接字文件  
• b: 块设备文件  
• c: 字符设备文件  
• p: 管道文件  
空文件或目录  
 -empty  
示例:find /app -type d -empty  

组合条件:  
与:-a  
或:-o  
非:-not !  
德·摩根定律:  
(非 A) 或 (非 B) = 非(A 且 B)   
(非 A) 且 (非 B) = 非(A 或 B)   
示例:  
!A -a !B = !(A -o B)  
!A -o !B = !(A -a B)  
  
根据文件大小来查找:  
-size [+|-]#UNIT  
常用单位:k, M, G,c(byte)  
#UNIT: (#-1, #]  
如:6k 表示(5k,6k]  
-#UNIT:[0,#-1]  
如:-6k 表示[0,5k]  
+#UNIT:(#,∞)  
如:+6k 表示(6k,∞)  
 
根据时间戳:  
以“天”为单位  
 -atime [+|-]#,   
#: [#,#+1)  
+#: [#+1,∞]  
-#: [0,#)  
 -mtime  
 -ctime  
以“分钟”为单位  
 -amin  
 -mmin  
 -cmin  
  
根据权限查找:  
 -perm [/|-]MODE  
MODE: 精确权限匹配  
/MODE:任何一类(u,g,o)对象的权限中只要能一位匹配即可,或关系,+   
从centos7开始淘汰  
-MODE:每一类对象都必须同时拥有指定权限,与关系  
 0 表示不关注  
• find -perm 755 会匹配权限模式恰好是755的文件  
• 只要当任意人有写权限时,find -perm +222就会匹配  
• 只有当每个人都有写权限时,find -perm -222才会匹配  
• 只有当其它人(other)有写权限时,find -perm -002才会匹配  

处理动作  
-print:默认的处理动作,显示至屏幕  
-ls:类似于对查找到的文件执行“ls -l”命令  
-delete:删除查找到的文件  
-fls file:查找到的所有文件的长格式信息保存至指定文件中  
-ok COMMAND {} \; 对查找到的每个文件执行由COMMAND指定的命令,对于每个文件执行命令之前,都会交互式要求用户确认  
-exec COMMAND {} \; 对查找到的每个文件执行由COMMAND指定的命令  
{}: 用于引用查找到的文件名称自身  
find传递查找到的文件至后面指定的命令时,查找到所有符合条件的文件一次性传递给后面的命令  
  
参数替换xargs  
由于很多命令不支持管道|来传递参数,xargs用于产生某个命令的参数,xargs
可以读入 stdin 的数据,并且以空格符或回车符将 stdin 的数据分隔成为参数  
许多命令不能接受过多参数,命令执行可能会失败,xargs可以解决  
注意:文件名或者是其他意义的名词内含有空格符的情况  
find和xargs的组合:find | xargs COMMAND  
示例:  
ls | xargs rm 删除当前目录下的大量文件  
find /sbin/ -perm +700 | ls -l 这个命令是错误的  
find /bin/ -perm /7000 | xargs ls -Sl 查找有特殊权限的文件,并排序  
find /bin/ -perm -7000 | xargs ls -Sl 此命令和上面有何区别?  
find -type f -name “*.txt” -print0 | xargs -0 rm 以字符nul分隔  

压缩、解压缩及归档工具

compress/uncompress

compress [-dfvcVr] [-b maxbits] [file ...]  
 -d 解压缩,相当于uncompress  
-c 结果输出至标准输出,不删除原文件  
-v 显示详情  
uncompress file.Z 解压缩  
zcat file.Z 不显式解压缩的前提下查看文本文件内容  
示例:zcat file.Z >file  

gzip/gunzip

gzip [OPTION]... FILE ...  
-d 解压缩,相当于gunzip  
-c 结果输出至标准输出,保留原文件不改变  
-# 指定压缩比,#取值为1-9,值越大压缩比越大  
gunzip file.gz 解压缩  
zcat file.gz 不显式解压缩的前提下查看文本文件内容  
示例:  
gzip -c messages >messages.gz  
gzip -c -d messages.gz > messages  
zcat messages.gz > messages  
cat messages | gzip > m.gz  

bzip2/bunzip2/bzcat

bzip2 [OPTION]... FILE ...  
-k keep, 保留原文件  
-d 解压缩  
-# 1-9,压缩比,默认为9  
bunzip2 file.bz2 解压缩  
bzcat file.bz2 不显式解压缩的前提下查看文本文件内容  

xz/unxz/xzcat

xz [OPTION]... FILE ...  
-k keep, 保留原文件  
-d 解压缩  
-# 压缩比,取值1-9,默认为6  
unxz file.xz 解压缩  
xzcat file.xz 不显式解压缩的前提下查看文本文件内容  

zip/unzip

打包压缩  
zip –r /backup/sysconfig /etc/sysconfig/  
解包解压缩  
unzip sysconfig.zip  
cat /var/log/messages | zip messages -  
unzip -p message.gz > message -p 表示管道  

tar工具

tar(Tape ARchive,磁带归档的缩写)  
tar [OPTION]...   
(1) 创建归档,保留权限  
 tar -cpvf /PATH/FILE.tar FILE...  
(2) 追加文件至归档: 注:不支持对压缩文件追加  
 tar -r -f /PATH/FILE.tar FILE...  
(3) 查看归档文件中的文件列表  
 tar -t -f /PATH/FILE.tar  
(4) 展开归档  
 tar -x -f /PATH/FILE.tar  
 tar -x -f /PATH/FILE.tar -C /PATH/  
(5) 结合压缩工具实现:归档并压缩 -j: bzip2, -z: gzip, -J: xz  

tar工具

--exclude 排除文件  
tar zcvf /root/a3.tgz --exclude=/app/host1 --exclude=/app/host2 /app  
-T 选项指定输入文件 -X 选项指定包含要排除的文件列表  
tar zcvf mybackup.tgz -T /root/includefilelist -X /root/excludefilelist  
split:分割一个文件为多个文件  
分割大的 tar 文件为多份小文件  
split -b Size –d tar-file-nameprefix-name
split -b 1M –d mybackup.tgz mybackup-parts  
split -b 1M mybackup.tgz mybackup-parts  
合并:  
cat mybackup-parts* >   mybackup.tar.gz   

cpio

 功能:复制文件从或到归档  
 cpio命令是通过重定向的方式将文件进行打包备份,还原恢复的工具,它可以解压以  
“.cpio”或者“.tar”结尾的文件  
 cpio [选项] > 文件名或者设备名  
 cpio [选项] < 文件名或者设备名  
 选项  
-o 将文件拷贝打包成文件或者将文件输出到设备上  
-O filename 输出到指定的归档文件名  
-A 向已存在的归档文件中追加文件  
-i 解包,将打包文件解压或将设备上的备份还原到系统  
-I filename 对指定的归档文件名解压
-t 预览,查看文件内容或者输出到设备上的文件内容
-F filename 使用指定的文件名替代标准输入或输出  
-d 解包生成目录,在cpio还原时,自动的建立目录  
-v 显示打包过程中的文件名称