[知识] Shell 编写常用知识(转载)

shell脚本总结

shell总结

 

shell脚本的本质是shell命令的有序集合

 

建立shell脚本的步骤:建立shell脚本,编写任意多行操作系统命令或shell命令,增加文件的执行权限,结束

 

shell变量

shell允许用户建立变量存储数据,但不支持数据类型。将任何赋给变量的值都解释为一串字符

shell有如下四种变量:用户自定义变量,位置变量,预定义变量,环境变量

 

用户自定义变量:

定义变量:COUNT=1

使用时前面加$:echo $COUNT

删除变量的赋值:unset COUNT

 

位置变量:

$0  与键入的命令行一样,包含脚本文件名

$1,$2...$9  分别包含第一个到第九个命令行参数

$#  包含命令行参数的个数

$@  包含所有命令行参数:“$1,$2...$9 ”

$?  包含前一个命令的退出状态

$*  包含所有命令行参数:“$1,$2...$9 ”

$$  包含正在执行进程的ID号

 

shell环境变量

CDPATH  用于cd命令的查找路径

HOME  用户主目录

PATH  路径

 

shell 程序和语句

shell程序由0到n条shell语句构成,shell语句包括三大类:功能性语句、结构性语句、说明性语句

 

说明性语句:以#开始的部分,不被解释执行

可以出现在程序的任意位置,可以单独一行,也可以接在执行语句的后面

 

功能性语句:任意操作系统命令、shell内部命令、自编程序、等

 

read  从标准输入读出一行,赋给后面的变量

read var   #把读入的数据全部赋给var

read var1 var2 var3     #把读入一行的第一、二个词分别赋给var1、var2,其他的都赋给var3

如果执行read语句时标准输入无数据,则程序在此停留等候,直到数据到来或终止运行

 

expr  主要用于简单的整数运算,包括 +  -  \*  /   %  等

 

 反撇号用于引用命令的运行结果

 

test  用于测试三种对象:字符串、整数、文件属性

可用[  ]代替,注意左右都至少一个空格

如:test  “$answer”  =  “yes”  #变量answer的值是否为字符串yes

test  $num  -eq  18  #变量num的值是否为整数18

test  -d  tmp    #测试tmp是否为一个目录名

 

 

 

结构性语句:条件测试语句、多路分支语句、循环语句、循环控制语句、后台执行语句

条件测试语句

if...then...else...fi

语法结构:

if  表达式

then  

命令表1  #一条或者若干条命令

else

命令表2  #一条或者若干条命令

fi

如果表达式为真,执行命令表1,否则执行命令表2

例子;

if [ -f S1 ]     #测试参数是否为文件

then

echo “File $1 exists”

fi

 

if [-d $HOME/$1]   #测试参数是否为目录

then

echo “File $1 is a directory”

fi

 

 

多路分支语句

case...esac

语法结构:

case 字符串变量  in     #case语句只能检测字符串变量

模式1)

命令表1

;;

模式2)

命令表2

;;

。。。。

*)                  # *表示其他所有

命令表n

;;

esac

例如:

case $1 in

file1)

echo “file1”

;;

file2)

echo “file2”

;;

*)

echo “others”

;;

esac

 

 

循环语句

for...do...done

当循环次数已知或者确定时,使用for循环语句来多次执行一条或一组命令,循环体由do和done来限定

for  变量名  in  单词表

do

命令表

done

说明:变量依次取单词表中的各个单词,每取依次单词,就执行一次循环体,循环次数为单词表中的单词个数,命令表中可以是一条或由分号隔开的多条命令

如果单词表是命令行上的所有位置参数时,可以省去  in  单词表

list=`ls`

for file in $list

do

if[ $1 = $file ]

then

echo “$file found”;

    exit; #退出shell脚本

fi

done

 

while...do...done

语法结构:

while  命令或表达式

do

命令表

done

说明:while首先测试其后的命令或表达式的值,如果为真,就执行一次循环体中的命令,然后再测试该命令或表达式的值,执行循环体,知道为假,退出循环

 

until...do...done

语法结构:

until 命令或表达式

do

命令表

done

与上面的相反

 

循环控制语句:

break  和  continue

break n   跳出n层

continue 马上跳转到最近一层循环的下一轮循环

continue  n  转到最近n层循环语句的下一轮循环上

 

 

 

shell函数

shell程序中,常把完成固定功能且多次使用的一组命令封装在一个函数中,每当要使用时,调用函数名即可

函数调用前必须先定义,即顺序上先定义函数,再调用

调用程序可以传递参数给函数,函数可以用return语句把运行结果返回调用程序

函数只在当前shell中起作用,不能输出到子shell中

 

shell函数定义格式

function funtion_name ()   #function可以省掉

{

...

}

 

函数调用方式

value_name = `function_name [arg1 arg2 ...]`    #函数结果返回给变量

或

function_name [arg1 arg2 ...]

echo $?           #获取函数返回的状态

 

函数变量的作用域

全局作用域:在脚本的其他地方都可以访问该变量

局部作用域:只能在声明的作用域内访问

 

局部变量的声明: Local  variable_name = value

 

脚本调试:

跟踪脚本执行结果:

在希望开始调试的地方插入 set -x

在希望结束调试的地方插入 set +x

 

 

---------------------------------------------------------------------

---------------------------------------------------------------------

Bash shell结构

1:shbang行:脚本的第一行,告之内核用哪个shell解释shell脚本,由#!加shell的完整路径组成

2:注释:#后面的为注释,可以在一行后

3:shell通配符或元字符:shell中字符意义比较特殊,如* ? [] > < 2> >> |等,防止这些字符被解释,则必须引用他们

4:局部变量:局部变量作用域在本shell中

5:全局变量:又称为环境变量,由内置的export命令创建,作用域在本shell及子shell中

6:提取变量值:$

7:参数:可以从命令行传递参数给脚本

8:命令替换:`A` $(A)  结果可以赋给一个变量或代替所在位置

---------------------------------------------------------------------

正则表达式

正则表达式是一种字符模式,在查找过程中匹配指定的字符,可以用特殊的元字符来控制它们,正则表达式都被置于两个正斜杠//之间

元字符:表达的是不同于字符本身的含义

本书中的元字符有两类:shell元字符、正则表达式元字符,它们各司其职,shell元字符是由shell解析的,就是下面所讲的文件名置换;正则表达式元字符是由各种执行模式操作的程序来解析的,如vi、grep、sed、awk

---------------------------------------------------------------------

正则表达式元字符:

^  行首定位

$  行尾定位

.  匹配单个字符

*  匹配0或多个重复的位于*前的字符

[]  匹配指定组字符中的任意一个 ;如[LlT]

[-] 匹配指定范围内的字符 ;如[x-yA-Z0-8]

[^] 匹配不在指定组内的字符

[^ - ]跟上面的相反

\  转移跟在后面的字符     #转义元字符,使之不被解释

\< 词首定位符     #定位以什么开头的词

\> 词尾定位符     #定位以什么结尾的词

---------------------------------------------------------------------

grep 家族

grep家族由grep、egrep、fgrep组成 

grep命令在文件中全局查找指定的正则表达式,并打印所有包含该表达式的行

一般格式:grep  [选项]   基本正则表达式  [文件]   

选项:-n 显示行号  -i 大小写不敏感  -w表达式作为词来查找,也就是不是一个词的一部分  -r 递归查找

基本正则表达式:可为字符串,如果为字符串,最好用“”如果是模式匹配,用‘’调用变量时,也应该使用“”

文件:可以为多个文件;如 A1 A2

常用举例子

grep -n “your” www    #文件www中查找含有your单词的行,且输出行号

grep -nw “your” www    #文件www中查找含以your做单词的行,且输出行号

grep -nr ‘[a-zA-Z0-9].you’ ./  #递归./ 中查找含有以a-z A-Z 0-9开始的单词的行,且输出行号

---------------------------------------------------------------------

find命令及xargs

find pathname -options [-print -exec -ok]

常用的options为name 此时记住要用引号将文件名模式引起来

find ./  “*org.txt”   #在当前目录及子目录中寻找以org.txt结尾的文件

find 找到文件后可用xargs对其操作

find ./  “*org.txt” | xargs ls

find ./  “*org.txt” | xargs grep “device”  #在结果中搜索device

---------------------------------------------------------------------

启动

系统启动后

->init->getty进程

->/bin/login  初始化环境,启动shell

->/bin/bash 执行/ect/profile,执行~/.bash_profile ~/.bash_login ~/.profile,执行~/.bashrc

->等待用户输入

---------------------------------------------------------------------

环境

一个进程的环境包括:变量等,它定义了可以从一个进程继承到下一个进程的特性

用户的shell配置定义在shell初始化文件中,bash shell有许多启动文件,这些文件可以执行source命令,对一个文件执行source命令会使得这个文件中的所有设置称为当前shell的一部分,也就是说不会创建子shell

登陆时,会执行~/.bash_profile文件执行source命令,如无,则source ~/.bash_login,若无,则source ~/.profile,这三个文件只能source一个,再source ~/.bashrc

~/.bashrc:包含特定的变量和别名,当一个新的bash shell启动或bash脚本启动时会自动执行source ~/.bashrc

在当前提示符下输入shell或bash启动的是子shell

/etc/bashrc:系统级的函数和别名可以在/etc/bashrc文件中设置,主提示符一般在这设置

~/.profile:是一个用户定义的初始化文件,它是被Bourne shell使用的,因此不能包括对bash shell的特定设置,运行bash时只有没找到其他文件时才source此文件,它允许用户定制和修改shell环境,也可以放应用程序的初始化

---------------------------------------------------------------------

source命令或dot命令(.)  和  ./命令

source命令式内置的bash命令,来自C shell

dot命令也就是. 来自Bourne shell

二者完全一样,都是一个脚本名作为参数,shell将在当前的shell环境中执行这个脚本,也就是不启动子shell,脚本中的设置的所有参数将成为当前shell环境的一部分。

./执行脚本时是创建子shell,脚本中的设置参数在脚本退出后就无效了。

 

例子:在家目录下的.bashrc中加入WANG=”ni hao”

然后. .bash.rc

此时执行内容为 echo “$WANG”的 脚本

 

如用 ./sh.sh 则无输出  #./执行时是在起一个子shell

如用source sh.sh或 . sh.sh则输出ni hao  #source是在本shell中执行

---------------------------------------------------------------------

bash shell元字符(通配符)

\  按字面含义解释后面的那个字符

&  在后台处理的进程

; 分隔命令

$  替换命令

*  匹配任意字符

?  匹配任意单个字符

[...] 匹配[]中的任意一个字符

[!...] 不匹配[]中!的任意一个字符

(cmds)  在子shell中执行命令

{cmds}  在当前shell中执行命令

---------------------------------------------------------------------

文件名置换

计算命令行时,shell会用元字符来缩写能够匹配某个特定字符组的文件名或路径名

将元字符展开为文件名或路径名的过程称为文件名替换或globbing

*    匹配文件(夹)名中的任意字符串

如:ls app*

cd cmdd*

?    匹配文件(夹)名中的任意一个字符

[...] 匹配[]中的任意一个字符

[!...] 不匹配[]中!的任意一个字符

如:ls [a-z]*.o   #匹配以a-z开头的已.o结尾的文件

ls [!0-9]*.o     #匹配以非0-9开头的已.o结尾的文件

---------------------------------------------------------------------

命令执行顺序

命令1 && 命令2  #命令1执行成功才会执行命令2

命令1 || 命令2  #命令1执行不成功才会执行命令2

用() 和 {}将命令结合在一起

 

 

---------------------------------------------------------------------

Bash shell变量

变量可分为两种:局部变量和环境变量

局部变量只在创建他们的shell中可用,环境变量作用域可以扩展到子shell中去

变量命名规则:可以是字母、0-9、下划线组成,必须以字母或下划线开头,其他字符都标志着变量名的终止,变量名大小写敏感

有两个内置命令可以用来创建变量,他们是declare、typset,其选项可以控制变量的设置方式,建议使用declare.

格式:declare  [选项]  变量=值

选项:-x  将变量设置成环境变量

      -r 将变量设置成只读变量

      -a 将变量当一个数组

---------------------------------------------------------------------

创建局部变量

1:变量赋值:变量=值    #注意等号周围不能有任何空白字符,如果想赋空,可以在等号后跟上换行符

2:内置命令declare  变量=值  #注意等号周围不能有任何空白字符,如果想赋空,可以在等号后跟上换行符

例子:

设置:round=world 或 round=”world nice”  #“”保护空白符

设置:declare round=world

输出:echo $round

设置:file.bak=”xxxx”   错,变量名中出现非法字符

local函数:函数内创建局部变量可以用local函数

---------------------------------------------------------------------

创建环境变量

环境变量,又被称为全局变量,作用域可以扩展到子shell中,通常环境变量用大写

环境变量是已经用export内置命令导出的变量,如果想设置环境变量,只需在设置变量时或赋值后使用export命令即可,declare 带-x也是设置环境变量

设置环境变量:

1:export 变量=值  #注意等号周围不能有任何空白字符,如果想赋空,可以在等号后跟上换行符

2:变量=值; export 变量    #注意等号周围不能有任何空白字符,如果想赋空,可以在等号后跟上换行符  

3:declare -x 变量=值  #注意等号周围不能有任何空白字符,如果想赋空,可以在等号后跟上换行符

---------------------------------------------------------------------

设置只读变量

只读变量是不能被重新定义或复位的特殊变量,但是如果使用declare定义的变量,可以重定义,不能复位

设置:name=”TOM”

readonly name   #设置只读

unset name  #不能复位

name=Jem  #不能重定义

设置:declare -r city=”shanghai”

unset city #不能复位

declare city=“beijin” #可以

---------------------------------------------------------------------

提取变量的值

在变量前加$

---------------------------------------------------------------------

复位变量

只要不被设置只读,局部变量和环境变量都可以用unset命令复位

格式:unset 变量名

---------------------------------------------------------------------

显示变量值

1:echo [选项]  变量   #echo将他的参数显示到标准输出上

选项:-e   #允许解释转义字符,如echo -e “\a”  \a转义为报警

如:echo The name is $NAME

echo -e “\a”  #报警

2:printf命令

---------------------------------------------------------------------

变量扩展修饰符

可以用一些专用修饰符来测试和修改变量,修饰符首先进行简单的条件测试,检查某变量是否已被设置,然后根据测试结果给变量赋值

${VA:-word}  #如变量VA已经设置且非空,则代入其值,否则代入word   临时替换默认值 

${VA:=word}  #如变量VA已经设置且非空,则代入其值,否则VA设置为word,代入VA永久替换默认值

${VA:+word}  #如变量VA已经设置且非空,则代入word,否则代入空值   临时替换默认值

${VA:?word}  #如变量VA已经设置且非空,则代入其值,否则输出word且从shell退出  基于默认值创建错误信息

 

注:不加冒号时,值为空也被认为已经设置

如:echo ${name-Joe}  #结果为空

echo ${name:-Joe}  #结果为Joe

echo ${namex:?”namex is undefined”}  

echo ${y?}  #如果y未设置,否则输出parameter null or not set

 

${VA:offset}  #获取变量VA值中位置从offset开始的字串

${VA:offset:length}  #获取变量VA值中位置从offset开始长度为length的字串  创建字串

如:var=notebook

echo ${var:0:4}   #结果note

---------------------------------------------------------------------

子串的变量扩展

模式匹配变量用来在串首或串尾截掉串的一部分,常用语删除路径名的头或尾

${变量%模式}  #将变量值的尾部与模式进行最小匹配,并将匹配到的部分删除

${变量%%模式} #将变量值的尾部与模式进行最大匹配,并将匹配到的部分删除

${变量#模式}  #将变量值的头部与模式进行最小匹配,并将匹配到的部分删除

${变量##模式} #将变量值的头部与模式进行最大匹配,并将匹配到的部分删除

${#变量}      #替换为变量中的字符个数,如果是*或@ ,长度则是位置参量的个数

如:

pathname=”/usr/bin/local/bin”

echo ${pathname%/bin*}  #结果/usr/bin/local/

echo ${pathname%%/bin*}  #结果/usr

echo ${pathname#/usr}  #结果/bin/local/bin

echo ${pathname##/usr}  #结果bin

echo ${#pathname}  #结果8

---------------------------------------------------------------------

位置参量

下面这组专用内置变量常称为位置参量,通常被shell脚本用来从命令行接受参数,或被函数用来保存传递给它的参数

$0  #指当前shell脚本的名称

$1-$9  #代表第一个到第9个位置参量

${10} ${11} #第10、11个位置参量,不用$10,$11

$#  其值为位置参量的个数,不含$0

$*  其值为所有的位置参量

$@  同$*

“$*”  其值为“$1 $2 $3”

“$@”  其值为“$1”“$2”“$3”

位置参数可以用set命令来设置、重置或复位

set --   #清除所有的位置参数

---------------------------------------------------------------------

其他特殊变量

$    #当前shell的pid

_    #当前sh的选项设置

?    #已执行的上一条命令的退出值

!    #最后一个进入后台的作用的pid

---------------------------------------------------------------------

引用

用来保护特殊的元字符不被解释和禁止参量扩展

引用有三种方式:反斜杠、单引号、双引号

需要引用的特殊元字符有:

;

&

()

{}

|

< > 

空格 tab 换行符

$ 

* [] ? 

1:单引号和双引号必须成对出现

2:单引号保护特殊元字符免受解释,双引号也能,但双引号允许处理变量替换字符$和命令替换字符``和\

3:双引号可以保护单引号,单引号可以保护双引号

4:如果有不匹配的引号,bash会出现次提示符

反斜杠:反斜杠用于引用(或转义)单个字符,使其免受解释。

单引号中的反斜杠不会被解释

如果在双引号中,反斜杠将保护$ ``和反斜杠免受解释

单引号:成对出现,保护所有元字符不被解释,打印双引号就必须用双引号将其括起来,或反斜杠转义

双引号:同单引号,但是允许进行变量替换$和命令替换``和\

 

简言之:单引号中什么都不被解释。双引号中$ `` \这三个会被解释,如不想解释用\转义

注意:``同$()是一样的,所以$(date)也会展开

---------------------------------------------------------------------

命令替换

命令替换的用处是将命令的输出结果赋给一个变量或将命令的输出结果代入命令所在位置

bash 允许使用两种格式:`命令`   和  $(命令)

执行扩展时,bash先执行命令,然后返回命令的标准输出,输出结果末尾的换行符都将被删除,如果不想删除,可用“”括起,如:echo “$(cal)”

如:echo “this is `date +%H`”   #this is 09

d=$(date)  #d存放命令date的结果

`命令`  \保留字面意思,除非后面跟$ ` \ 且``中$  \生效,可用\转义之,``中再有``的话必须用\转义

$(命令)  中的所有特殊字符都不会解释

命令替换可以被嵌套,``必须使用\`转义,如echo `basename \`pwd\` `  #其中转义后的`pwd`也是当做命令替换的,如:$(basename $(pwd))

---------------------------------------------------------------------

数组

bash 中可以创建一维数组,数组允许将一列词放到一个变量名中,可以用内置命令declare -a创建,或直接给变量名一个下标来创建,如x[0]=5   索引值为从0开始的整数,数组无上限,索引也不必是有序数。

取出数组中某个元素,语法为:${数组名[索引]}

创建数组:

declare 、local 、read-only内置命令也可以带-a选项来声明一个数组。read -a是读取一列词到数组中

declare -a va_name=(item1 item2 item3 ...)

declare -ar va = {item1 item2 item3 ...}

states=(ME [3]=CA [2]=CT)  #数组states第0元素为ME  3元素为CA  2元素为CT

declare -a nums=(45 33 100 65)

name=(TOM Dick Harry)

echo ${va_name[*]}   #输出数组所有元素

echo ${#va_name[*]}  #输出数组大小

取消定义:unset name 或 unset name[2]

---------------------------------------------------------------------

函数

bash函数用于在当前shell环境(不派生子shell)通过函数名执行一组命令,函数常常用于提高脚本的模块化程度。

函数可被重复调用。函数必须定义后才会被调用

定义函数:有两种格式声明一个bash函数

1:函数名后跟一对圆括号,再跟函数定义

function_name () { commands;commands; }

2:function关键词后跟函数名及函数定义,圆括号可选

function function_name { commands;commands;}

function function_name () { commands;commands;}

注意:命令之间用;隔开,最有一条命令必须以分号终结。花括号两侧空格是必须的。

传递给函数的任何参数被当做函数内的位置参数,一个函数的位置参数相对于函数来说是局部的

内置命令local允许在函数定义中创建局部变量

 

函数可以递归调用本身

函数中的命令是在当前shell环境下执行

全局函数:同变量一样,函数作用域可以扩展到子shell,只要用export -f全局化函数

export -f 函数名

说明:当函数命令列在单独的行,可以不用分号,最后一条还是需要。如果列在同一行,必须用分号隔开

如:function welcome { echo “Hi $1 and $2”; }

welcome tom joe  #传递参数给函数,结果为Hi tom and joe

set jane anna lizzy

echo $1 $2

jane anna

unset -f welcome #清除函数定义

 

列出和清除函数

declare -f #列出该shell中定义的所有函数及他们的定义

declare -F #同上,只列出函数名

unset -f   #清除函数定义

---------------------------------------------------------------------

管道

管道(pipe)将管道符左侧命令的输出作为到管道符右侧命令的输入,一条管道线可能不止一个管道

管道符用竖杠 | 表示,一般形式:命令1 | 命令2 | 命令3

---------------------------------------------------------------------

shell内置命令

shell中有许多内置到它的源码中的命令,shell无需到磁盘中定位他们,执行速度速度快很多。

常见内置命令如下:

:   #空命令

.   #在当前进程的环境下执行程序,同source

alias #命令重命名

unalias #删除重命名

bg  #将作业放到后台

cd 

exit

fg #将作业放到前台

jobs #列出放在后台的作业

set #设置选项和位置参数

unset #删除变量值或函数

declare

export

---------------------------------------------------------------------

Bash shell编程

shell脚本:当命令不在命令行上执行,而是通过一个文件执行时,该文件被称为shell脚本,脚本以非交互的方式运行。它先查找环境变量所指定的环境文件,通常为.bashrc,然后从该文件开始执行,然后才开始执行脚本中的命令

创建shell脚本的步骤:

1:第一行:#!/bin/bash

2:编写内容

shell脚本结构:由一组Unix/linux命令、bash shell命令、程序结构控制语句、注释 组成

3:增加执行权限  chmod +x files

---------------------------------------------------------------------

读取用户输入

read命令

read是一个内置命令,用于从终端或文件读取一个输入行,直到换行符,行尾的换行符被转换成一个空字符,如果后面未跟变量名,则读取的行被赋给内置变量REPLY,可以用read中断脚本的运行,直至输入回车键

read var                 #把读入的数据全部赋给var

read var1 var2 var3     #把读入一行的第一、二个词分别赋给var1、var2,其他的都赋给var3

---------------------------------------------------------------------

算术运算

整数运算(declare和let命令)

declare命令:可以用declare -i 定义整形变量,如果给一个整形变量赋一个字符串,则bash将把变量赋值为0,可以对已定义的整形变量执行算术运算(如果未定义为整形变量,内置的let命令也允许算术操作),如果给整形变量赋一个浮点数值,则bash报语法错误。数字可以用不同基数的数字表示

如:declare -i num

num=5 + 5 #错

num=5+5  #对

num=”5 + 5” #对

num=5.6 #错

 

declare -i  将列出所有已经设置的整形变量及其值

 

用不同的基数表示数字

格式:variable=base#number

如:declare -i x=017

x=2#101

x=8#17

let命令:let命令式bash shell内置命令,用来执行整形算术运算和数值表达式测试;可用(())表示let命令

let命令在执行算术运算时,不需要用$来展开变量,参数含有空格则用“”包含

如:let “i = i + 2”

---------------------------------------------------------------------

位置参数

用户可以通过命令行向脚本传递信息,跟在脚本名后的用空白符分隔的每个词都称为参数,可以在脚本中使用位置参数来引用命令行参数

shell环境中的位置参数作用域在本shell,shell脚本执行时跟在后面的参数相当于局部的位置参数,只对本脚本生效

如:脚本内容 echo “$1”

执行时 source sh.sh wang  #则输出wang

如果在命令行set hahaha

执行时 source sh.sh wang  #则输出wang

执行时 source sh.sh  #则输出hahaha

 

set命令与位置参数

可以用set命令设置或重设位置参数

带参数的set命令将重置位置参数,重置的是shell环境中的位置参数。清除所有位置参数,可以用set -- 命令

---------------------------------------------------------------------

条件结构和流程控制

条件结构能够根据某个特定的条件是否满足,来执行相应的任务

bash可以检测两种类型条件:命令成功或失败,表达式为真或假。在任何一种类型的测试中,都要使用退出状态,为0表示命令成功或表达式为真,非0表示命令失败或表达式为假。退出状态保存在状态变量?中
简言之:bash中执行命令成功与否和表达式为真或假都会改变退出状态变量?

 

 

内置命令test

单方括号的test命令:通常使用内置的test命令测试表达式的值,test命令可以被链接到方括号上,这样即可使用单独的test命令,也可通过把表达式用单括号括起来,来测试表达式的值

用test命令或[]测试表达式时,表达式中的shell元字符不会被解释。由于对变量进行单词分离,因此包含空白符的字符串必须用引号括起来

双方括号的test命令:用[[]]来测试表达式的值,其中对变量不进行单词分离,但可以通过元字符扩展进行模式匹配。包含空白符的字符串必须用引号括起来,如果一个字符串(不管含不含空白符)仅仅是在表达式中作为一个普通字符串,而不是一个模式的一部分,则必须用引号括起来

逻辑操作符&&、||代替了与test命令一起使用的-a -o选项

 

说明:test可以用来测试字符串、数字、文件。test命令中表达式等号两侧必须有空格。单方括号第一个方括号后必须有空格,表达式两侧必须有空格。

简言之:

[]的测试表达式:表达式可为字符串比较、数字比较、文件测试。表达式等号两侧必须有空格,方括号必须有空格。表达式中的shell元字符不会被扩展。对变量进行单词分离,所以包含空格时必须用引号括起来

[[]]的测试表达式:表达式可为字符串比较、数字比较、文件测试。表达式等号两侧必须有空格,方括号必须有空格。表达式支持shell元字符,如果为普通字符串,防止误认为模式,必须用双引号括起来。支持逻辑&& || ,对应test中的-a -o   ,其中对变量不进行单词分离,即使变量由多个词组成也不需要双引号括起来

 

let和带双圆括号的算术运算符(())

对于计算算术表达式,可以不用test而用let命令,let命令含有丰富的操作符,let命令等同(())

(())中的变量不需要使用$,操作符两侧必须空格,圆括号两侧必须空格

简言之:let命令更适合整形算术运算和数值表达式测试

---------------------------------------------------------------------

if命令

if 结构后面的命令可以是bash内置命令或可执行程序,如ls

bash shell中跟在if后面的则是一条或一组命令。

 

exit 命令和变量?  exit用于终止脚本并返回到命令行

检查空 检查变量的值是否为空时,必须用双引号把空括起来,否则test命令失败

 

if 命令

then

命令

elif 命令

then

命令

elif 命令

then

命令

fi

---------------------------------------------------------------------

null命令(shell内置命令)

:代替null命令

null命令不做任何事,只是返回退出状态0(注意没退出,不同于exit 0)

---------------------------------------------------------------------

case命令

格式:

case 变量 in

表达式1)

命令组

;;

表达式2)

命令组

;;

...

*)

命令组

;;

esac

变量的值逐一与表达式相比,符合则执行命令组,并跳到esac后继续执行

表达式可以使用shell通配符,还可以使用 | 将两值相或

---------------------------------------------------------------------

循环命令

bash shell提供三种类型的循环:for   while   until

---------------------------------------------------------------------

for命令

格式:

for  变量  in   词表

do

命令组

done

注:词表可以通过执行命令获得,如  for  W  in $(date)

词表支持shell元字符:如 for file in memo[1-5]  

注意词表是$* $@ “$*” “$@”时的区别

如果没有“in 词表”则相当于“ for 变量 in $* ”

如果命令行参数为*,则它表示当前目录下的所有文件。

---------------------------------------------------------------------

while命令

格式:

while 测试命令

do

命令(命令组)

done

注:while 后的测试命令可以用test 或let或其他

---------------------------------------------------------------------

until命令

同while命令,只不过相反,也就是until 后的命令执行不成功时执行命令组

---------------------------------------------------------------------

循环控制命令

shift命令

shift 命令将参数左移指定次数,如:shift 5,没给参数时移动一次,当不够移动时,输出信息。

shift常用于while循环中遍历位置参数列表时。

如:while (( $# > 0 ))

do

echo $1   #$1值不断变化

shift

done

 

ture命令:总是已状态0退出

 

break命令

break用于跳出循环,层数为跳出几层

continue命令 跳过本次循环,继续下次,参数为调到哪一层循环起点,默认为跳到最近一层

---------------------------------------------------------------------

I/O重定向 与 子shell

shell可通过管道或重定向将输入从文件输入改为从循环读取输入,输出到循环改为输出到文件

shell启动一个子shell来处理I/O重定向和管道,循环结束后,在循环中定义的所有变量对脚本的其余部分都是不可见的

重定向一般是到文件,管道一般是到命令

将循环的输出重定向到一个文件:bash循环的输出不仅可以送到标准输出,还可以通过管道送到文件

将循环的输出管道到一个命令

---------------------------------------------------------------------

后台执行循环

循环可以在后台执行,这样就可以继续往下执行其他程序而不必等待循环处理全部完成

---------------------------------------------------------------------

函数

函数在当前环境中运行,函数共享调用它的脚本中的变量,还允许给函数传递参数,可以使用local功能在函数内部创建局部变量

在函数中调用exit将退出整个脚本。

函数中的return语句,返回函数执行的最后一条命令的退出状态,或返回指定参数值

使用export -f把函数导出到子shell

使用declare -f可以列出所有的函数名及其定义

如果函数保存在其他一些文件中,可以用source和dot命令把他们载入到当前脚本中

函数可以递归调用,次数没限制

 

清除函数

从内存中清除某个函数,使用unset命令

unset 函数名

 

函数的参数和返回值

当前shell环境中的变量对函数是可见的,在函数中对环境所做的任何改动也是会对shell环境生效的。

函数可以使用位置参数向函数传递参数,位置参数是函数私有的,也就是说,函数对参数的操作不会影响在函数外使用的任何位置参数

内置local功能:函数私有的局部变量,在函数退出后随即消失。

内置return命令:用来退出函数并将控制回转到程序调用函数的位置,如果未给return赋值,则返回最后一条命令的退出状态,如果赋值了,则该值保存在变量?中。可以是0-255之间整数。

获取函数的结果可以用 命令替换,如:$(函数名)  `函数名`

函数可以定义在文件中,当需要时,调用source或dot命令跟上函数名就能激活文件中的函数,函数会被加载到shell内存空间

---------------------------------------------------------------------

调试

带-n选项的bash命令,能对脚本进行语法检查,但不去运行任何一条命令,如语法错误,则报错,否则不显示任何内容

最常见的调试脚本的手段是用带-x选项的set命令,或是调用带-x选项和脚本名为参数的bash

此时shell对脚本的每条命令处理过程为:先执行替换,接在显示,再去执行它。shell显示脚本中的行时,会在行首添加加号+

调试选项:

bash -x 脚本名  #回显   在变量替换之后,执行命令之前,显示脚本的每一行

bash -v 脚本名  #详细   在执行之前,按输入的原样打印脚本中的各行

bash -n 脚本名  #不执行 解释但不执行命令

set -x  #打开回显  跟踪脚本执行

set +x  #关闭回显  关闭跟踪功能

---------------------------------------------------------------------

调试shell脚本

风格问题

1:加注释

2:定义有意义的变量名

3:确保健壮性

错误类型

---------------------------------------------------------------------
————————————————
版权声明:本文为CSDN博主「wangchaoqun1997」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wangchaoqun1997/article/details/36480131
CC 4.0 BY-SA 版权协议网址:https://creativecommons.org/licenses/by-sa/4.0/deed.z

[工具] Shell 批量检测服务器和远程 tcp 端口的联通状态

#!/bin/bash
#作者:朱明宇
#名称:批量检测服务器和远程 tcp 端口的联通状态
#作用:批量检测服务器和远程 tcp 端口的联通状态,并将此服务器无法联通的端口存储到 $checklist 文件里
#使用方法:
#1.将此脚本和端口清单 $portlist 文件放在同一目录下
#2.端口清单 $portlist 每一个端口占用一行,格式为:<要联通端口号对应的 IP 地址>:<要联通的端口号>:<端口功能>
#3.在此脚本的分割线内写入相应的内容
#4.给此脚本增加执行权限
#5.执行此脚本,并将要测试的服务器 IP 地址跟在脚本的后面,例:. <脚本名> <服务器 IP 地址1> <服务器 IP 地址1> ......
#注意:此脚本执行前必须要先保证能无秘钥远程这些远程服务器
#注意:此脚本会清空 $checklist
#注意:执行此脚本前确保 telnet 命令已经安装
#注意:执行此脚本可能有些慢

#######################我是分割线:两条分割线里的内容需要使用者自己配置########################

portlist=tcp_ports.txt #存放要测试的 tcp 端口的文件
checklist=tcp_ports_checklist.txt #存放测试结果的文件

#######################我是分割线:两条分割线里的内容需要使用者自己配置########################

echo  > $checklist

maxnum=`cat $portlist | wc -l`

for hosts in $*

do

echo $hosts >> $checklist

for i in `seq 1 $maxnum`
do

ips=`sed -n $[i]p $portlist | awk -F':' '{print $1}'`
ports=`sed -n $[i]p $portlist | awk -F':' '{print $2}'`
remarks=`sed -n $[i]p $portlist | awk -F':' '{print $3}'`

ssh $hosts "(sleep 1;) | telnet $ips $ports 2>&1" | grep 'timed out' >> $checklist

if [ $? == 0 ];then
echo "`sed -n $[i]p $portlist`" >> $checklist
echo >> $checklist
fi

done

echo >> $checklist
done

[命令] Linux 文件管理命令 sed 的使用(修改和打印文本的行)

内容目录:
内容一:sed 格式

内容二:sed 选项

内容三:sed 的参数

内容四:sed 的使用案例
4.1 使用 p 参数打印某一行数据的案例
4.2 使用 a 参数在某一行下面追加一行数据的案例
4.3 使用 i 参数在某一行上面插入一行数据的案例
4.4 使用 c 参数替换某一行数据的案例
4.5 使用 d 参数删除某一行的案例
4.6 使用 s 参数替换某一行某些数据的案例
4.7 使用 h、H、g、G 参数复制和粘贴的案例
4.7.1 sed 命令的工作原理
4.7.2 h、H、g、G、d、D 参数的讲解
4.7.2.1 h、H、g、G、d、D 参数的作用简介
4.7.2.2 h、H、g、G、d、D 的功能示意图
4.7.3 案例

具体的内容:
内容一:sed 格式
sed <选项> <参数> <文件>

内容二:sed 选项
(1)-n 或 --quiet 或 --silent 仅显示处理后的内容,没处理的内容就不显示了
(2)-i 实现数据的变更
(3)-e <脚本> 或 --expression=<脚本> 以指定的脚本来处理输入的文本
(4)-r 支持扩展正则
(5)-f <脚本文件> 或 --file=<脚本文件> 以指定的脚本文件来处理输入的文本
(6)-h 或 --help 显示帮助内容
(7)-V 或 --version 显示版本信息

内容三:sed 的参数
(1)p 打印某一行的数据
(2)a 在某一行下面追加一行的数据
(3)i 在某一行上面插入一行的数据
(4)c 替换某一行的数据
(5)d 删除某一行
(6)s 替换某一行的某些数据
(7)h、H、g、G 复制和粘贴某些行的数据

内容四:sed 的使用案例
4.1 使用 p 参数打印某一行数据的案例
# sed -n 2p test.txt #在 test.txt 文本里打印第二行的数据
# sed -n 2,4p test.txt #在 test.txt 文本里打印第二行到第四行的数据
# sed -n '$p' test.txt #在 test.txt 文本里打印最后一行的数据
# sed -n '/eternalcenter/p' test.txt #在 test.txt 文本里打印包含 eternalcenter 的数据
# sed -n '/eternalcenter$/p' test.txt #在 test.txt 文本里打印以 eternalcenter 结尾的数据
# sed -n $= test.txt #在 test.txt 文本里输出总行数
# sed -n 'p;n' test.txt #在 test.txt 文本里输出奇数行
# sed -n 'n;p' test.txt #在 test.txt 文本里输出偶数行

4.2 使用 a 参数在某一行下面追加一行数据的案例
# sed 2a eternalcenter test.txt #在 test.txt 文本里在第二行下面追加一行 eternalcenter
# sed /abc/a eternalcenter test.txt #在 test.txt 文本里在 abc 那一行下面添加一行 eternalcenter
# sed /^a/a eternalcenter test.txt #在 test.txt 文本里在以 a 开头的行下面添加 eternalcenter
# sed "/^\[a\]/a eternalcenter" test.txt #在 test.txt 文本里在以 [a] 开头的行下面添加 eternalcenter

4.3 使用 i 参数在某一行上面插入一行数据的案例
# sed 2i eternalcenter test.txt #在 test.txt 文本里在第二行上面插入一行 eternalcenter
# sed /abc/i eternalcenter test.txt #在 test.txt 文本里在 abc 那一行上面添加一行 eternalcenter
# sed /^a/i eternalcenter test.txt #在 test.txt 文本里在以 a 开头的行上面添加 eternalcenter
# sed "/^\[a\]/i eternalcenter" test.txt #在 test.txt 文本里在以 [a] 开头的行上面添加 eternalcenter

4.4 使用 c 参数替换某一行数据的案例
# sed 2c eternalcenter test.txt #在 test.txt 文本里将第二行替换成 eternalcenter
# sed /abc/c eternalcenter test.txt #在 test.txt 文本里将 abc 那一行替换成 eternalcenter
# sed /^a/c eternalcenter test.txt #在 test.txt 文本里将以 a 开头的那一行替换成 eternalcenter
# sed "/^\[a\]/c eternalcenter" test.txt #在 test.txt 文本里将以 [a] 开头的那一行替换成 eternalcenter

4.5 使用 d 参数删除某一行的案例
# sed 2d test.txt 在 test.txt 文本里删除第二行
# sed /abc/d test.txt 在 test.txt 文本里删除包含 abc 的那一行
# sed /^a/d test.txt #在 test.txt 文本里删除以 a 开头的那一行
# sed "/^\[a\]/d" test.txt #在 test.txt 文本里删除以 [a] 开头的那一行
# sed '2,4d' test.txt #在 test.txt 文本里删除第二行到第四行

4.6 使用 s 参数替换某一行某些数据的案例
# sed 's/eternalcentre/eternalcneter/' test.txt #在 test.txt 文本里将所有行的第一个 eternalcentre 换成 eternalcenter
# sed 's/eternalcentre/eternalcneter/g' test.txt #在 test.txt 文本里将所有行的所有 eternalcentre 换成 eternalcenter
# sed 's/.*eternalcentre.*/eternalcneter/' test.txt #在 test.txt 文本里将包含 eternalcentre 的行换成 eternalcenter
# sed '3s/eternalcentre/eternalcenter/2' 1.txt #在 test.txt 文本里将第三行的第二个 eternalcentre 换成 eternalcenter
# sed 's/^/eternalcenter/g' test.txt #在 test.txt 文本里在所有行前面添加 eternalcenter
# sed '2s/.*/eternalcenter/' test.txt #在 test.txt 文本里将第二行替换成 eternalcenter
# sed '$s/.*/eternalcenter/' test.txt #在 test.txt 文本里将最后一行替换成 eternalcenter
# sed '2,3s/.*/eternalcenter/' test.txt #在 test.txt 文中里将第二到第三行替换成 eternalcenter

# sed "s/^\(.*\)\(eternalcenter\)\(.*\)$/\3\2\1/" test.txt
或者
# sed -r "s/(.*)(eternalcenter)(.*)/\3\2\1/" test.txt
#在 test.txt 文本里将 eternalcenter 前面的数据和后面的数据对调位置

# sed 's/.//1;s/.$//' test.txt #在 test.txt 文本里删除每行的第一个字符和最后一个字符
# sed 's/.//2;s/.$//' test.txt #在 test.txt 文本里删除每行的第二个字符和最后一个字符
# sed -r 's/[0-9]//g;s/^( )+//' test.txt #在 test.txt 文本里删除所有的数字和空格
# sed 's/[A-Z]/(&)/g' test.txt #在 test.txt 文本里将所有的大写字母都添加括号
# sed '7,9s/^/#/' test.txt #在 test.txt 文本里给第七行和第九行前面添加 "#"

4.7 使用 h、H、g、G 参数复制和粘贴的案例
4.7.1 sed 命令的工作原理
(1)从第一行开始一行一行地读取文本里的内容
(2)每读取一行就将数据存入到 pattern space 里面
(3)在 pattern sapce 中执行 sed 命令
(4)再打印 pattern space 中的内容然后将其清空
(5)之后重复以上操作再开始读取文本里的下一行
(6)pattern space 里的数据可以存储到 hold space 里面

(
补充:
pattern space 相当于处理数据的流水线
hold space 相当于暂时存储数据的仓库
)

4.7.2 h、H、g、G、d、D 参数的讲解
4.7.2.1 h、H、g、G、d、D 参数的作用简介
(1)g 将 hold space 中的内容拷贝到 pattern space 中,原来 pattern space 里的内容清除
(2)G 将 hold space 中的内容 append 到 pattern space\n 后
(3)h 将 pattern space 中的内容拷贝到 hold space 中,原来的 hold space 里的内容被清除
(4)H 将 pattern space 中的内容 append 到 hold space\n 后
(5)d 删除 pattern 中的所有行,并读入下一新行到 pattern 中
(6)D 删除 multiline pattern 中的第一行,不读入下一行

4.7.2.2 h、H、g、G、d、D 的功能示意图
P H     P H     P H
1    h  1 1  d    1

P H     P H     P H     P H
2 1  G  2 1  H  2 1  d    1
        1       1 2       2
                  1       1

P H     P H     P H
3 2  G  3 2  h  3 3
  1     2 1     2 2
        1       1 1

P H     P H
3 2  g  2 2
  1     1 1
           
(
注意:
(1)这里的 P 指的是 pattern space
(2)这里的 H 指的是 hold space
)

(
补充:
h 其实就是清空现在粘贴板里的内容然后重新复制
H 其实就是不清空现在粘贴板里的内容然后再再原来粘贴版的内容基础上再追加复制
g 其实就是替换粘贴
G 其实就是追加粘贴
)

4.7.3 案例
# sed -e '1h' -e '3G' test.txt #将第一行的数据添加到第三行后面
# sed -e '1h' -e '3g' test.txt #将第一行的数据替换第三行
# sed -e '1h' -e '2H' -e '3G' test.txt #将第一行和第二行的数据添加到第三行后面
# sed -e '1h' -e '2H' -e '3g' test.txt #将第一行和第二行的数据替换第三行
# sed -e '/^a/h' -e '3G' 1.txt #将第一个以 a 开头的行的数据添加到第三行后面
# sed -e '/^a/h' -e'/^a/H' -e '3G' 1.txt #将第一个和第二个以 a 开头的行的数据添加到第三行后面

[命令] Linux 文件查看命令 grep 的使用(打印文本的行)

内容目录:
内容一:grep 使用正则表达式匹配的案例
内容二:grep 显示行号的案例
内容三:grep 取反匹配的案例
内容四:grep 完全匹配的案例
内容五:grep 匹配区分大小写的案例
内容六:grep 统计匹配成功次数的案例
内容七:grep 将匹配成功的部分自动添加颜色的案例
内容八:grep 将匹配成功的部分自动取消颜色的案例

具体的内容:
内容一:grep 使用正则表达式匹配的案例
# grep -E '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192
IPADDR=192.168.8.31
GATEWAY=192.168.8.55
或者
# egrep '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192
IPADDR=192.168.8.31
GATEWAY=192.168.8.55

内容二:grep 显示行号的案例
# egrep -n '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192
16:IPADDR=192.168.8.31
18:GATEWAY=192.168.8.55

内容三:grep 取反匹配的案例
# egrep -v '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens192
UUID=5cda4d03-45c9-4856-80a6-f0bd0962d871
DEVICE=ens192
ONBOOT=yes
NETMASK=255.255.255.0
ZONE=public

内容四:grep 完全匹配的案例
# egrep -o '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192
192.168.8.31
192.168.8.55

内容五:grep 匹配区分大小写的案例
# egrep -i '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192
IPADDR=192.168.8.31
GATEWAY=192.168.8.55

内容六:grep 统计匹配成功次数的案例
# egrep -c '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192
2

内容七:grep 将匹配成功的部分自动添加颜色的案例
# egrep --color=auto '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192
IPADDR=192.168.8.31
GATEWAY=192.168.8.55

内容八:grep 将匹配成功的部分自动取消颜色的案例
# egrep --color=no '([1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}' /etc/sysconfig/network-scripts/ifcfg-ens192  
IPADDR=192.168.8.31
GATEWAY=192.168.8.55

[命令] Linux 文件查看命令 awk 的使用(打印文本的列)

内容目录:
内容一:awk 格式

内容二:awk 的 -F 选项

内容三:awk 的常用内置变量

内容四: awk 的使用案例
4.1 awk 基础打印的案例
4.2 awk 自定义分割列符号的案例
4.3 awk 打印常量的案例
4.4 awk 使用正则表达式匹配的案例
4.5 awk 使用比较运算符匹配的案例
4.6 awk 计算的案例
4.7 awk 计数的案例
4.8 awk if 判断语句计数的案例
4.9 awk for 循环实现同时批量输出值的名称和值的案例
5.0 awk 打印表格的案例

具体的内容:
内容一:awk 格式
# awk <选项> '<条件>{<指令>}' <文件名>
# awk <选项> ' BEGIN{<指令>} {<指令>} END{<指令>}' <文件名>

(
补充:在这里
BEGIN{ } 里的指令只执行 1 次,并且是最先执行
{ } 里的指令会一行行地执行文件里的内容
END{ } 里指令只执行 1 次,并且是最后执行
)

内容二:awk 的 -F 选项
awk 默认是以空格分割列,但是也可以通 -F 参数指定分割每一列的符号
例:
-F: 的意思就是以 “:” 符号分割每 1 列
-Fa 的意思就是以 “a” 字母分割每 1 列

内容三:awk 的常用内置变量
(1)$0 文本当前行的全部内容
(2)$1 文本的第 1 列
(3)$2 文本的第 2 列
(4)$3 文本的第 3 列

(补充:“$” 号后面的数字以此类推)

(5)NR 文本当前行的行号
(6)NF 文本当前行的列数,也就是一共有几列
(7)$(NF-1) 文本倒数第一列
(8)$(NF-2) 文本倒数第二列
(9)$(NF-3) 文本倒数第三列
(10), 代表空格
(11)\t 代表 tab 制表位,就是比一个空格更多的空格

内容四: awk 的使用案例
4.1 awk 基础打印的案例
# awk '{print $1,$3}' test.txt #打印文档第 1 列和第 3 列
# awk '{print $(NF-2)}' /etc/passwd #打印倒数第 2 列
# awk -F: '{print NR,NF}' passwd.txt #打印每一行的行号和列数
# df -h | awk '{print $5}' #打印前一个命令结果的第 5 列
# df -h / | tail -1 | awk '{print $5}' #打印前一个命令结果的第 5 列

4.2 awk 自定义分割列符号的案例
# awk -F: '{print $1,$7}' /etc/passwd #将 ”:“ 视为分割符
# awk -F [:.] '{print $1,$10}' /etc/passwd #将 ”:“ 和 “.” 视为分割符

4.3 awk 打印常量的案例
# awk -F: '{print $1,"的解释器是:",$7}' /etc/passwd

4.4 awk 使用正则表达式匹配的案例
# awk '/Failed/{print $11}' /var/log/secure #打印包含 Failed 的行的第 11 列
# awk -F: '/bash$/{print}' /etc/passwd #打印以 bash 结尾的行,并且将 “:” 视为分割符
# awk -F: '/^(root|adm)/{print $1,$3}' /etc/passwd #打印以 root 或者 adm 开头的行的第 1 列和第 3 列,并且将 “:” 视为分割符
# awk -F: '$1~/root/' /etc/passwd #打印第 1 列包含 root 的行,并且将 “:” 视为分割符
# awk -F: '$7!~/nologin$/{print $1,$7}' /etc/passwd #打印第 7 列不以 nologin 结尾的行的第 1 列和第 7 列,并且将 “:” 视为分割符
# ifconfig eth0 | awk '/RX p/{print $5}'  #打印前一个命令包含 Rx p 的行的第 5 列
# df -h | awk '/\/$/{print $4}' #打印前一个命令以 / 结尾的行的第 4 列

4.5 awk 使用比较运算符匹配的案例
# awk -F: 'NR==3{print}' /etc/passwd #打印行号等于 3 的行,并且将 “:” 视为分割符
# awk -F: '$3>=1000{print $1,$3}' /etc/passwd #打印第 3 列数值大于 1000 的行的第 1 列和第 3 列,并且将 “:” 视为分割符
# awk -F: '$3<10{print $1,$3}' /etc/passwd #打印第 3 列数值小于 10 的行的第 1 列和第 3 列,并且将 “:” 视为分割符
# awk -F: '$1=="root"' /etc/passwd #打印第 1 列为 root 的行,并且将 “:” 视为分割符
# awk -F: '$3>10 && $3<20' /etc/passwd #打印第 3 列数值大于 10 并且小于 20 的行,并且将 “:” 视为分割符
# awk -F: '$3>1000 || $3<10' /etc/passwd #打印第 3 列数值大于 1000 或者小于 10 的行,并且将 “:” 视为分割符

4.6 awk 计算的案例
# awk 'BEGIN{print x+1}' #0+1=1(注意:这里的 x 可以不定义,直接用,默认值为 0)
# awk 'BEGIN{x++;print x}' #x=0+1
# awk 'BEGIN{x=8;print x+=2}' #x=8+2
# awk 'BEGIN{x=8;x--;print x}' #x=8-1
# awk 'BEGIN{print 2+3}' #2+3=5
# awk 'BEGIN{print 2*3}' #2*3=6
# awk 'BEGIN{print 3.2+3.5}' #3.2+3.5=6.7
# awk 'BEGIN{ print 23%8}' #23 除 8 余 7
# seq  200 | awk  '$1%3==0' #找 200 以内 3 的倍数
# seq 100 | awk '$1%7==0||$1~/7/' #找 100 以内 7 的倍数或者包含 7 的数

4.7 awk 计数的案例
# awk 'BEGIN{x=0}/bash$/{x++} END{print x}' /etc/passwd #计算以 bash 结尾的行数
# awk -F: '{if($3<=1000){i++}}END{print i}' /etc/passwd #计算第 3 列小于等于 1000 的行数,并且将 “:” 视为分割符
# awk -F: '{if($3>1000){i++}}END{print i}' /etc/passwd #计算 3 列大于 1000 的行数,并且将 “:” 视为分割符
# awk -F: '{if($7~/bash$/){i++}}END{print i}' /etc/passwd #计算第7列以 bash 结尾的行数,并且将 “:” 视为分割符

4.8 awk if 判断语句计数的案例
# awk -F: '{if($3<=1000){i++}else{j++}}END{print i,j}' /etc/passwd #计算第 3 列小于等于 1000 的行数和第 3 列大于 1000 的行数,并且将 “:” 视为分割符
# awk -F: '{if($7~/bash$/){i++}else{j++}} END{print i,j}' /etc/passwd #计算第 7 列以 bash 结尾的行数和第 7 列不以 bash 结尾的行数,并且将 “:” 视为分割符

4.9 awk for 循环实现同时批量输出值的名称和值的案例
# awk 'BEGIN{a[0]=0;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}' #创建数组 a,其中 a[0]=0 a[1]=11 a[2]=22,并且将数组 a 打印出来
# awk '{ip[$1]++} END{for(i in ip) {print ip[i],i }}' /var/log/httpd/access_log #统计所有的 IP 以及每一个 IP 访问的次数
# awk '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log | sort -nr #统计所有的 IP 以及每一个 IP 访问的次数,并排序

5.0 awk 打印表格的案例
# awk -F: 'BEGIN{print "User\tUID\tHome"}{print $1 "\t"  $3  "\t"  $6}END{print "Total",NR,"lines."}' /etc/passwd #在开始打印一行,在结尾打印一行,并且将 “:” 视为分割符