SHELL 基础

一,特殊的shell变量

变量含义

$0 脚本名字

$1 位置参数 #1

$2 - $9 位置参数 #2 - #9

${10} 位置参数 #10

$# 位置参数的个数

"$*" 所有的位置参数(作为单个字符串) *

"$@" 所有的位置参数(每个都作为独立的字符串)

${#*} 传递到脚本中的命令行参数的个数

${#@} 传递到脚本中的命令行参数的个数

$? 返回值(上个命令是否成功执行)

$$ 脚本的进程ID(PID)

$- 传递到脚本中的标志(使用set)

$_ 之前命令的最后一个参数

$! 运行在后台的最后一个作业的进程ID(PID)

 

例:

#!/bin/bash

if [ "$#" -eq "2" ];then

     echo "My first parameter is $1"

     echo "My second parameter is $2"

 else

     echo "Usage: `basename $0` first second"

     echo "You provided $# parameters,but 2 are required."

 fi

二,字符串测试比较

(一定得加双引号""

 

算术比较       字符串比较

-eq 等于         = 等于

                 == 等于

-ne 不等于       != 不等于

-lt 小于         \< 小于 (ASCII) *

-le 小于等于

-gt大于          \> 大于 (ASCII) *

-ge 大于等于

-z 字符串为空

-n 字符串不为空

 

三,文件类型的测试操作

操作测试条件

-e 文件是否存在

-s 文件大小为0 则真

-f 是一个标准文件

-d 是一个目录

 -r 文件具有读权限

-h 文件是一个符号链接

 -w 文件具有写权限

-L 文件是一个符号链接

-x 文件具有执行权限

-b 文件是一个块设备

-c 文件是一个字符设备

-g 设置了sgid标记

-p 文件是一个管道

 -u 设置了suid标记

-S 文件是一个socket

 -k 设置了"粘贴位"

-t 文件与一个终端相关联

-N 从这个文件最后一次被读取之后, 它被修改过

-O 这个文件的宿主是你

-G 文件的组id与你所属的组相同

! "" (反转上边的测试结果)

 

F1 -nt  F2 文件F1比文件F2*

F1 -ot  F2 文件F1比文件F2*

F1 -ef  F2文件F1和文件F2都是同一个文件的硬链接 *

三,参数替换和扩展

表达式含义

${var} 变量var的值, $var相同

${var-DEFAULT} 如果var没有被声明, 那么就以$DEFAULT作为其值 *

${var:-DEFAULT} 如果var没有被声明, 或者其值为空, 那么就以$DEFAULT作为其值 *

${var=DEFAULT} 如果var没有被声明, 那么就以$DEFAULT作为其值 *

${var:=DEFAULT} 如果var没有被声明, 或者其值为空, 那么就以$DEFAULT作为其值 *

${var+OTHER} 如果var声明了, 那么其值就是$OTHER, 否则就为null字符串

 

 

${var:+OTHER} 如果var被设置了, 那么其值就是$OTHER, 否则就为null字符串

${var?ERR_MSG} 如果var没被声明, 那么就打印$ERR_MSG *

${var:?ERR_MSG} 如果var没被设置, 那么就打印$ERR_MSG *

${!varprefix*} 匹配之前所有以varprefix开头进行声明的变量

${!varprefix@} 匹配之前所有以varprefix开头进行声明的变量

${#string} $string的长度

${string:position} $string, 从位置$position开始提取子串

 

 

${string:position:length} $string, 从位置$position开始提取长度为$length的子串

${string#substring} 从变量$string的开头, 删除最短匹配$substring的子串

${string##substring} 从变量$string的开头, 删除最长匹配$substring的子串

${string%substring} 从变量$string的结尾, 删除最短匹配$substring的子串

${string%%substring} 从变量$string的结尾, 删除最长匹配$substring的子串

 

${string/substring/replacement} 使用$replacement, 来代替第一个匹配的$substring

${string//substring/replacement} 使用$replacement, 代替所有匹配的$substring

${string/#substring/replacement} 如果$string的前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring

${string/%substring/replacement} 如果$string的后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring

 

 

expr match "$string" '$substring' 匹配$string开头的$substring*的长度

expr "$string" : '$substring'   匹配$string开头的$substring*的长度

expr index "$string" $substring   $string中匹配到的$substring的第一个字符出现的位置

expr substr $string $position $length$string中从位置$position开始提取长度为$length的子串

expr match "$string" '\($substring\)' $string的开头位置提取$substring*

expr "$string" :'\($substring\)' $string的开头位置提取$substring*

expr match "$string"'.*\($substring\)' $string的结尾提取$substring*

expr "$string" :'.*\($substring\)' $string的结尾提取$substring*

一些结构的汇总表达式解释

中括号

if [ CONDITION ] 测试结构 (注意两边有空)

if [[ CONDITION ]] 扩展的测试结构

Array[1]=element1 数组初始化

[a-z] 正则表达式的字符范围

大括号

${variable} 参数替换

${!variable} 间接变量引用

{ command1; command2; . . . commandN; } 代码块

{string1,string2,string3,...} 大括号扩展

圆括号

( command1; command2 ) shell中执行的命令组

Array=(element1 element2 element3) 数组初始化

result=$(COMMAND) 在子shell中执行命令, 并将结果赋值给变量

>(COMMAND) 进程替换

<(COMMAND) 进程替换

双圆括号

(( var = 78 )) 整型运算

var=$(( 20 + 5 )) 整型运算, 并将结果赋值给变量

 

引号

"$variable"    ""引用

'string'       ""引用

后置引用

result=`COMMAND` 在子shell中运行命令, 并将结果赋值给变量

 

 

五,正则表达式与通配符

     正则表达式

      ---------用来在文件中的字符串的,

  ---------是包含匹配(字符串的一部分能匹配字符串)

  例:搜索aa只要包含aa字符串的文本都能搜索出来)grep   awk   sed

  

    通配符?* []

    -----------用来搜索文件名的,完全匹配(必须得完一样)  

    -----------之所以通配符是用来匹配文件名的,是为ls这些命令只认识通配符

    ----------因为是完全匹配,假如说有aa aabb两个文件,ls aa命令时,则只能找到aa一个文件

   ---------*号也是匹配0次或多次,任意字符

 

元字符(即特殊字符,通配符)

返斜线 \   为脱义符

元字符;

. 匹配换行符外的任意字符

[a-z0-9] 匹配集合中的任意单字符

[^a-z0-9]   匹配不在集合中的任意单字符

\d 匹配单个数字  等效于[0-9]

\D 匹配非数字,等效于[^0-9]  

\w 匹配数字型的字符  等效于[0-9]

\W 匹配非数字型的,字符 相当于[^0-9]

\s 匹配空格

\S 匹配非空格

\n 匹配换行符

\r 匹配回车符

\t 匹配制表符

\0 匹配空值字符

 

锚定字符;

\b 匹配字边界(不在[]中)

\B 匹配非字边界

^ 匹配行首

$ 匹配行尾   (和行首一样,行首行尾不仅包含可见字符,也可能是不可见的)

\A 匹配字符串开头

\Z 匹配字符串或行未尾

\z 只匹配字符串未尾

\G 匹配前一次m//g

 

重复次数字符

x?         匹配0个或1x

x*    匹配0个或多个

x+    匹配1个或多个

(xyz)+    匹配1个或多个

x{m,n} 匹配m个到n个(m要比n小)

 

替换字符;

|   

例;(was|were|will

匹配waswerewill之一  

思考;三者之间匹配2个呢???

 

其它字符;

\12 匹配八进制数

\x811 匹配十六进制数

\cX 匹配控制字符

\e 匹配ASCII

\x{NUMBER} 匹配十六进制形式给出的Unicode

常用正则表达式

*       ------前一个字符匹配0次或多次(只能代表前一个字符)

. -----------代表除了换行符之外的任意一个字符

^ ---------匹配行首(例:^hello   匹配以hello为行首的字符)

$ --------匹配行尾(例 hello$)

[] --------匹配中括号中的多个字符中的一个(选一个字符)

[^  ] ----匹配除中括号中字符以外的任意一个字符

\ ---------------脱义符,取消后面特殊符号的意义

\{n\} -----------表示前面的字符恰号出现n次,

(例子:[0-9]\{4\}表示[0-9]出现4A\{n\}表示出现4A

\{n,\} -------表示前面的字符出现不小于n

(例:[0-9]\{4,\}表示四位及四位以上的数)

\{n,m\} --------表示前面的为字符,最少出现n次,最多出现m

(例子:[a-z]\{6,8\}匹配68位的小写字母)

,grep命令

grep参数

语法:
grep   -[acinv]   '搜索内容串'   filename
-a  将二进制文档以文本方式处理
-c  计算找到的符合行的次数
-i  忽略大小写
-n  顺便输出行号
-v  反向选择,即显示不包含匹配文本的所有行

-h 查询多文件时不显示文件名。
-l 查询多文件时只输出包含匹配字符的文件名。
-s 不显示不存在或无匹配文本的错误信息。
- E参数,这一扩展允许使用扩展模式匹配。

 

grep举例

关于匹配的实例:
grep -c "48" test.txt 统计所有以“48”字符开头的行有多少
grep -i "May" test.txt 不区分大小写查找“May”所有的行)
grep -n "48" test.txt 显示行号;显示匹配字符“48”的行及行号,相同于 nl test.txt |grep 48
grep -v "48" test.txt 显示输出没有字符“48”所有的行)
grep "471" test.txt 显示输出字符“471”所在的行)
grep "48;" test.txt 显示输出以字符“48”开头,并在字符“48”后是一个tab键所在的行
grep "48[34]" test.txt 显示输出以字符“48”开头,第三个字符是“3”或是“4”的所有的行)
grep "^[^48]" test.txt 显示输出行首不是字符“48”的行)
grep "[Mm]ay" test.txt 设置大小写查找:显示输出第一个字符以“M”或“m”开头,以字符“ay”结束的行)
grep "KD" test.txt 显示输出第一个字符是“K”,第二、三、四是任意字符,第五个字符是“D”所在的行)
grep "[A-Z][9]D" test.txt 显示输出第一个字符的范围是“A-D”,第二个字符是“9”,第三个字符的是“D”的所有的行
grep "[35]..1998" test.txt 显示第一个字符是35,第二三个字符是任意,以1998结尾的所有行
grep "4/{2,/}" test.txt 模式出现几率查找:显示输出字符“4”至少重复出现两次的所有行
grep "9/{3,/}" test.txt 模式出现几率查找:显示输出字符“9”至少重复出现三次的所有行
grep "9/{2,3/}" test.txt 模式出现几率查找:显示输出字符“9”重复出现的次数在一定范围内,重复出现2次或3次所有行
grep -n "^$" test.txt 显示输出空行的行号
ls -l |grep "^d" 如果要查询目录列表中的目录 同:ls -d *
ls -l |grep "^d[d]" 在一个目录中查询不包含目录的所有文件
ls -l |grpe "^d..x..x" 查询其他用户和用户组成员有可执行权限的目录集合

 

七、printfecho命令

区别

echo只是回显没有变量替换功能;

printf是有的
举例:

假如我们定义好变量a='hello world'
echo "%s" $a  显示的结果就是%s
printf "%s\n" $a  显示的结果就是hello world

 

linux中只有printf命令       

awk中,有printprintf命令

 

语法

printf '输出类型输出格式' 输出内容

输出类型:

%ns:输出字符串。n是数字指代输出几个字符。
%ni:输出整数。n是数字指代输出几个数字。
%m.n:输出浮点数。m和n是数字,指代输出的整数位数和小数

%8.2代表共输出8位数,其中2位是小数,6位是整数。

举例

[root@localhost ~]# printf %s 1 2 3 4 5 6

123456[root@localhost ~]# printf %s %s %s 1 2 3 4 5 6

%s%s123456[root@localhost ~]# printf '%s %s %s' 1 2 3 4 5 6

1 2 34 5 6[root@localhost ~]# printf '%s\t%s\t%s\n' 1 2 3 4 5 6

1 2 3

4 5 6

[root@localhost ~]# printf '%s' $(cat student.txt)

1furongF852fengjF603cangF70[root@localhost ~]#

[root@localhost ~]# printf '%s\t%s\t%s\t%s\n' $(cat student.txt)

1 furong F 85

2 fengj F 60

3 cang F 70

说明:以上printf打印文件的方式,其实用awk来实现更好控制

八、算术运算

1(())双括号形式

z=$(($a+2)) --正确

z=$((a+3)) --正确

echo $((b+3)) --正确

说明:

使用双括号的形式最后,可以进行多种运算

而其它的如expr set  则支持的运算不全

 

2bc命令                                                                       

它是linux下的计算器,即可以命令行中使用,也可以在脚本文件中使用         

说明;                                                                  

它最大的特点就是支持小数运算                                    

                                                                

echo 4.5+5|bc   --结果9.5                                 

seq -s "+" 10 |bc   --结果是55   它计算的是1+2+3+....10    

补充 echo "scale=2; 2.3/32"|bc                               

scale=2表示有保留小数点后两位                                   

obase=2表示是以二进制形式显示出来                               

obase=16表示以十六进制形式显示出来                              

                                                                

解释:                                                                  

即在表达式后面使用|bc ,即将表达式,交给bc来处理   

      

3,$[ 表达式] $((表达式))效果差不多

 

九、shell变量从终端输入

补充;

---一种方法,我们使用命令行传参来进行赋值的  $1  $2  $3 ...

---另一方法 直接赋值

---还可以使用read[参数][变量名]

 

例;read -p a1 a2  回车

输入12 34     回车

则即把 12 34 分别赋值给a1a2

read -t 3 -p "请输入"  a1 a2

显示请输入  3秒  如果3秒内没有动作 则自动退出执行命令

 

- p   表示后面是给用户看的

-t    后面的数字表示是待等的时间

 

2echo -n "请输入"    --这是给用户看的  -n表示不换行(请输入后,不换行)

read  a  b ---这是要输入变量

 

3,直接使用

read a  b   则会等待用户输入

 

注意;

如输入    12.3  45  56

则;a值是12.3   b值是 45 56

 

--说明;以下是判断输入的变量是否为数字,如果不为数字则重新输入

read -t 10 -p "请输入:" a  b

expr $a + 0 > &/dev/null

[ $? -ne 0 ] && read -t 10 -p "请重输入:" a  b

expr $b + 0 > &/dev/null

[ $? -ne 0 ] && read -t 10 -p "请重输入:" a  b

 

十、条件测试

文件测试

语法说明;

格式1test< >

格式2[ ]      --推荐使用此方法,所以后面不写[[]]格式的用法

格式3[[ ]]  

(())只能适用于整数测试

 

例;

一般操作文件时,都要先判断文件是否存在

test -f  file && echo 1 ||echo 0   

----即判断文件存不存在,则不会echo 1  而会运行 echo 0

test ! -f file && echo 1||echo 0

---和上面相反

 

[ -f file ] && echo 1 || echo 0

[ -f file -a -d foler ] && echo 1 || echo 0

[ -f file -r -d foler ] && echo 1 || echo 0

----即判断文件存不存在,则不会echo 1  而会运行 echo 0

----注意中括号两边有空格

----  - o表示或者  ,-a 表示and

 

说明;

-f 文件是否存在

-d 目录是否存在

-e 文件或目录是否存在

-w/-r/-x   权限判断

-s   文件存在,并且文件大小大于0则返回真

字符串测试

是否相同

是否长度为零

是否为NULL  bash区分null和零长度)

 

[ -z "str" ] 若长度为0 zero 则为真

[ -n "str" ] 若长度非0  则为真

[ "str1"="str2" ]

[ "str1"=="str2" ]  相等   则为真

[ "str1"!="str2" ] 不等  则为真

-----以上字符串操作,必须要用""括起来

 

特别说明;

如果是(())

测试数字时,则使用 ==  <  >  <=  >=    

-----(说明在使用圆括号(())时,必须使用双等号==,否则会被认为是赋值 )

-----它只能测试数字

 

如果是[]  --推荐使用此方法,

测试数字时,则使用 -eq -ne -gt  -ge  -lt -le    (等于,不等于,大于,小于,小于等于)

测试字符中时,由使用 ==  =  !=   -z -n

测试文件时,则使用-f -d -e -x   多文件时使用 -a  -o  

 

如果混着用,即[]使用<  > =  >= 。。则必须\<进行转义

十一、分支循环

if语句

1,单分支结构;

if 条件 ; then

.....

fi

--(如果then和 条件在同一行,则中间必须有分号;)

 

2,双分支结构

if 条件; then

.....

else

.....

fi

 

3,多分支结构

if 条件 ;then

.....

elif  条件 ; then

.....

else

......

fi

case语句

        case分支语句的格式如下:

            case $变量名 in

                模式1

            命令序列1

            ;;

                模式2

            命令序列2

         ;; 

                *

            默认执行的命令序列     ;; 

            esac 

 

 case语句结构特点如下:

        case行尾必须为单词“in”,每一个模式必须以右括号“)”结束。

        双分号“;;”表示命令序列结束。

        匹配模式中可是使用方括号表示一个连续的范围,如[0-9];使用竖杠符号“|”表示或。

        最后的“*)”表示默认模式,当使用前面的各种模式均无法匹配该变量时,将执行“*)”后

    的命令序列。

 

例如;

read a

case "$a" in

1) echo "输入为1"

;;

2echo "输入为2"

;;

[3-9]echo "输入为3-9"

;;

11 | 12) echo "输入为1112"

*echo "输入为其它"

esac

 

while循环

语法;

while 条件

do

.....

done

 

解释;

条件满足则一直做

 

例如;

while true --死循环

do

uptime     --可以看系统时间,用户系统负载

sleep 2

done

for循环

1》语法;

for 变量名  in  变量取值列表

do

........

done

 

说明;

其中in  变量取值列表”  可省略,

如果省略可相当于 for 变量名  in   "$@"  即从所有的命令行参数中取值

解释;

即变量依次被赋值成取值列表中的值

然后去执行后面的语句

 

2》语法;

for 变量名 in {5..1}     ----使用 for 变量名 in  `seq -s  " " 5 -1  1`

do

......

done

解释;

{5..1}表示,为序列,从51

{a..z}表字,26个英文字母的序列

 

 

3》语法;(说明,ksh不支持此种语法)

for ((exp1;exp2;exp3))

do

.....

done  

解释;

语法和Cfor语法一样

 

例如

for((i=0;i<=9;i++))

do

echo $i

done

 

例如;

 打印出5 4 3 2 1

 for num in 5 4 3 2 1

 do

  echo $num

 done

 

 例如;则打印出来的全是目录

  for i in `ls -F|grep /`

  do

  echo $i

  done

 

 

seq的用法;

1>> seq -选项  LAST

2>> seq -选项  FIRST  LAST

3>> seq -选项  FIRST INCREMENT  LAST

 

例如;

seq 5

seq 1 5

seq 1  2 10    ---中间数字表示步长,,步长可以是小数(例如;seq 1  0.1 10

seq 10  -2  1    ---返向,数字表示步长,负号表示减少

 

选项;

-w   指定输出数字同宽

-s   指定分隔符

-f   指定格式

 

例;

seq -w 10    

结果是;

01

02

。。。

10

 

seq -s "-"  10

结果是; 1-2-3-。。。-10

 

seq -f "%3g" 1 100

结果是;

  1

  2

  。。。

 20

  。。。

100    

 

seq -f "str%g" 10

结果是;

str1

str2

..

str10

退出分支或程序

breakcontinue,exit用法;

break ----结束循环体,向下执行

continue---路过本次循环,去执行done,再判断

exit----退出程序

 

 

十二、函数

函数名(){

。。。。

。。。。。

return n

}

或者

function 函数名(){

。。。。

。。。。。

return n

}

 

 

 

 

 

 

 

 

 

调用方式:

1》直接用函数名就好了,

函数名

---不需要带()

---定义时没有参数 ,但调用时,是可以带参数的

 

2》带参数函数的调用

函数名 参数1  参数2  (和脚本命令行带参数一样)

获取函数返回值

 

方法1使用return 返回时

check_count () {

略。。。。。。。

return $sum_count

}

##执行函数

check_count

#获取函数返回值

a=`echo $?`

方法2使用echo方法

nowtime() {

echo `date +"[%Y-%m-%d %H:%M]"`

}

 

##获取当前时间

now_time=`nowtime`

 

 

 

 

 

 

 

 

 

 

 

 

十三、数组

下标从0开始

1,数组的定义

数组名=(value1 value2  value3 value4...)

 

echo ${#数组名[@]}   

echo ${#数组名[*]}

--以上都可获取数组长度

 

echo ${数组名[0]}

---取数组中第1个元素

 

echo ${数组名[*]}

echo ${数组名[@]}

----遍历打印数组

 

2,数组的赋值

 数组名[0]=4

  ----给第数组中第1个元素赋值成4

  数组名[6]=8

---如果数组长度小于7,则此时相当于增加数组元素,

 

3,数组元素的删除

unset 数组名[0]

---删除数组中第1个元素

unset 数组名

---删除整个数组

 

4,数组元素的替换

因为数组也算是变量的一种,所以它也适用于变量字符串的一些操作

例如;

 arr=(1 2 3 4 5)

echo ${arr[@]:1:3}  ---截取下标为13的元素

echo ${arr[@]/5/6}  ---让数组的值为5的元素,换成6

十四、find命令

格式;                                                                               

find  路径 - 选项  【-print  -exec -ok】                                                                                                                        

选项:                                                                          

-name "....."  按文件名查找                                             

-type                                                                   

f    普通文件                                                   

d    目录                                                       

b    块设备                                                     

c    字符设备                                                   

p     管道设备                                                  

l     链接文件                                                  

-depth                                                                  

在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。                                                                         

参数:                                                                  

-printfind命令将匹配的文件输出到标准输出。                           

    -execfind命令对匹配的文件执行该参数所给出的shell命令。                           

     相应命令的形式为'command' { } \;                        

     注意{ }\;之间的空格。                                

     -ok: 和-exec的作用相同,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。

find exec配合

1

# find . -type f -exec ls -l { } \;

-rw-r--r--   1 root    root   34928 2003-02-25  ./conf/httpd.conf

-rw-r--r--   1 root    root   12959 2003-02-25  ./conf/magic

-rw-r--r--   1 root    root   180   2003-02-25  ./conf.d/README

---find命令匹配到了当前目录下的所有普通文件,并在-exec选项中使用ls -l命令将它们列出

     

2

 find logs -type f -mtime +5 -exec rm { } \;

---/logs目录中查找更改时间在5日以前的文件并删除它们

 

3

find . -name "*.conf" -mtime +5 -ok rm { } \;

< rm ... ./conf/httpd.conf >  n

--find命令在当前目录中查找所有文件名以.LOG结尾、更改时间在5日以上的文件,

---并删除它们,只不过在删除之前先给出提示。

--y键删除文件,按n键不删除。

 

4,      

find /etc -name "passwd*" -exec grep "sam" { } \;

sam:x:501:501::/usr/sam:/bin/bash

--find命令首先匹配所有文件名为“ passwd*”的文件,

--例如passwdpasswd.oldpasswd.bak

---然后执行grep命令看看在这些文件中是否存在一个sam用户

find命令和xargs命令配合

1

#find . -type f -print | xargs file

--查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件

2

$ find / -name "core" -print | xargs echo "" >/tmp/core.log

--在整个系统中查找内存信息转储文件(core dump) ,然后把结果保存到/tmp/core.log 文件中

3

# find . -type f -print | xargs grep "hostname"

--grep命令在所有的普通文件中搜索hostname这个词:

总结;

find命令配合使用execxargs可以使用户对所匹配到的文件执行几乎所有的命令。

十五、xargs命令

-0

 当sdtin含有特殊字元时候,将其当成一般字符,想/'空格等                                                    

 

例如:root@localhost:~/test#echo "//"|xargs  echo                                                   

  

    root@localhost:~/test#echo "//"|xargs -0 echo                                                         

  

                                                                                                 

-a

 file 从文件中读入作为sdtin,(看例一)                                                                   

-e

 flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止

-p

 当每次执行一个argument的时候询问一次用户。(例三)                                                       

-n

 num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。(例四)                     

-t

 表示先打印命令,然后再执行。(例五)                                                                     

-i

 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给{},可以用{}代替。(例六)           

-r

 no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。(例七)                             

-s

 num 命令行的最好字符数,指的是xargs后面那个命令的最大命令行字符数。(例八)                              

  

                                                                                                          

-L

  num Use at most max-lines nonblank input lines per command line.-s是含有空格的。                        

-l

  同-L                                                                                                    

-d

 delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符(例九)         

-x

 exit的意思,主要是配合-s使用。                                                                           

-P

 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。       

 

定义一个测试文件,内有多行文本数据:

 

 

 

-n 选项,指定几行内容,分割成一小块,

 

 

 

以下是-i  -I  的区别 ,-I (即大写的),可以指定xargs扩展时,把什么字符替换掉,替换成输入的内容。

-i (即小写的),默认是把{}  这个字符串替换成输入的内容。

 

 

十六、sort命令

原理;

 sort将文件的每一行作为一个单位,相互比较,

 比较原则是比较首字符,按ASCII码值进行比较,

 最后默认将他们按升序输出。  

  -u              排序后去重

  -r              逆序排(降序)

  -o  原文件名    排完序后,将内容更新到原文件,

(原内容将会被清空,使用重定向符到原文件时,则会清空原文件)

  -n               以数值作比较(而非以首字符)

  -t  间隔符

  -k  列数    比较每一行中,指定的列的首字符 (而非每一行中首字符)

  -b   忽略前面一行中的所有空白部分,从第一个可见字符进行比较

举例:

[root@Fedora6 huang]# ls |sort -t . -k 1 -n -r

111111111111.txt

33312.txt

2.txt

1.txt

 

[root@Fedora6 huang]# ls |sort -t . -k 1 -r

33312.txt

2.txt

1.txt

111111111111.txt

sort 去重

1,假如有文件1.txt

 

2,则排重后

 

 

 

 

 

 

 

 

 

 

 

 

 

 

十一、awk编程

优点

解决了cut命令不能很好识别 空格作为分隔符的列的不足                         

解决了printf不能很好的格式输出的不足                                       

它可以识别任何作为分隔符的列(例: 分号,空格 ,TAB,)                     

它比较复杂,它不仅可以进行字符串的截取,也可以进行函数调用,判断,流程控制

由于以上原因,一般也叫做awk编程                                            

它默认也是空格作为分隔符的   

语法                                                  

awk  -F 分隔符 '条件1{动作1}条件2{动作2}。。。' 文件名    

注意:

不写条件,默认条件值为1

BEGIN, END  也是条件,(一个是在遍历文件前,一个是在遍历文件后)

内部变量

 

 

 

 

 

例:

        awk 'END{print NR}'  1.txt   --可以打印出文件中有多少行

杂项                                           

FS 用法:

(相当于在命令行模式下使用-F 指定分隔符)

 例;

         awk -F ":" '{print $1}'   --命令行模式

         {BEGIN{FS=":"}{print $1}}  --放在文件中的写法

初始化(即未定义时的默认值)

字符串变量初始化为空字符串""

  数值变量初始化为0

 

print   printf

print   --自动在应该输出的每行后面加个\n,没有格式化控制输出

printf   --不会换行(需要人为加\n),它可以有格式化控制输出

 

1,普通模式:

awk '/pattern/{action}' files

 

patter  ---是一个正则表达式, (如果不指定pattern,则对所有文件的每一行都执行action)

action  ----又是一系列命令

files  ------表示待操作的文件 (如果不指定,则输入是STDIN)

2,表达式模式

awk '(expression){action}' files

awk '(expr1) && (expr2) {action}'  files

awk '(expr1) || (expr2) {action}'  files

 

expression  --是一个比较表达式,也可以是复合表达式

其它同上。

 

#awk 都是以文本中一行一行的进行操作处理的。每处理一行,进行除了BEGINEND语句之外的操作

#$0  表示整行(以本行本来的面目显示)

#awk '{print $0}'

#awk  如果后面没有跟文件由默认是STDIN  等待输入

3,文件模式:

即写在 ’ ’ 中的命令,也可以单独写在文件中

比较操作

awk中可以执行的比较操作有

<

>

<=

>=

!=

awk '($2>3){print $1,$3}'   --当第2列值大于3时,指印出指定内容

awk '($2>3)&&($2<5){print $1,$3}'   --当第2>3<5时打印出指定内容

awk '($2<5){print $1,$3};($2>5){print $2}'   --$2>5 打印$2 ; 当$2<5打印 $1 $3

BEGINGEND

二者都不参于文本中每行的处理,只是做此初始化和善后的工作;

二者必须大写

基本语法:

awk '

    BEGIN { actions }

    /pattern/ { actions }

    /pattern/ { actions }

    END { actions }

' files

说明:

多个{}之间,可以略去分号;也可以不省略。

流控制(if while for

将流控制语句放在{}执行块中

 

 

 

if(表达式) #if ( Variable in Array )
语句1
else
语句2

 

如果你为了方便Unix awk判断也方便你自已阅读,你最好将多个语句用{}括起来

if(表达式)

{语句1}

else if(表达式)
{语句2}
else
{语句3}

 

1.while语句

格式:

while(表达式)

{语句}

 

 

for循环有两种格式:

格式1

for(变量 in 数组)

{语句}

例:

for(k in ENVIRON)
{
    print k"="ENVIRON[k];
}

格式2

for(变量;条件;表达式)

{语句}

例:

for(i=0;i<=100;i++)
{
    total+=i;
}

 

 

 

 

 

变量的应用举例

ps -ef|grep -v grep |grep puaf01|grep -E "nosi_monitor|run_fts|run_pps|run_shm|run_bps|run_stat|run_unt|run_exp|md5|"  > 1.txt

 

cat  1.txt|awk '\

BEGIN {fts_count=0;pps_count=0;shm_count=0;bps_count=0;stat_count=0;unt_count=0;exp_count=0;md5_count=0};\

\

{if ($0 ~ /.*run_fts.*/) {fts_count += 1} \

if ($0 ~ /.*run_pps.*/) {pps_count += 1}\

if ($0 ~ /.*run_shm.*/) {shm_count += 1}\

if ($0 ~ /.*run_bps.*/) {bps_count += 1}\

if ($0 ~ /.*run_stat.*/) {stat_count += 1}\

if ($0 ~ /.*run_unt.*/) {unt_count += 1}\

if ($0 ~ /.*run_exp.*/) {exp_count += 1}\

if ($0 ~ /.*md5.*/) {md5_count += 1}};\

\

END {printf("fts=%s,\npps=%s,\nshm=%s,\nbps=%s,\nstat=%s,\nunt=%s,\nexp=%s,\nmd5=%s\n"),\

fts_count,pps_count,shm_count,bps_count,stat_count,unt_count,exp_count,md5_count}'

 

 

调用外部命令举例

1,将当前目录 下的面文件取模,依次MV到对应的目录下面

ls |awk -F "_" '{print $(NF-1),$(NF-1)%3,$0};\

{\

if($(NF-1)%3==0){cmd="mv "$0 " ../dir1";system(cmd)}\

if($(NF-1)%3==1){cmd="mv "$0 " ../dir2";system(cmd)}\

if($(NF-1)%3==2){cmd="mv "$0 " ../dir3";system(cmd)}\

\

}; END{a="file_count:";print a" "NR}'\

 

## 注:以上要在字符串中解析出$0,必须将$0写在引号外

 

2,去不同的目录下面,将文件备份到一个文件夹中

cd /uniocs/users/Billapp/csdata/gsm;

ls | xargs -n1 -i echo "/uniocs/users/Billapp/csdata/gsm/{}" | awk '{cmd="mv "$0"*  ../gsm_bak_test";print cmd;system(cmd)}'

 

 

传递外部变量到AWK

语法:

awk -v 变量=$SHELL中的变量  ‘{ 语句块 }

 

例子:

 

AWK去重

语法:

 awk  '!(a[$0]++)'  文件

 

首先准备一个文本文件,随便写个文件,包含重复行数据的即可,或者你可以参考我这里的文件:

 

CodingAnts@ubuntu:~/awk$ cat dup

hello world

awk

coding ants

hello world

awk

hello world

awk

coding ants

coding ants

 

  共有9行,后面6行都是重复的前面的几行,最终的效果应该是只显示上面重点显示的那几行,先来看看效果:

 

CodingAnts@ubuntu:~/awk$  awk  '!(a[$0]++)'  dup

hello world

awk

coding ants

 

原理:

  awk的程序指令由模式和操作组成,即Pattern { Action }的形式,如果省略Action,则默认执行 print $0 的操作。

 

  实现去除重复功能的就是这里的Pattern!(a[$0]++)

 

步骤:

  1,在awk中,对于未初始化的数组变量,在进行数值运算的时候,会赋予初值0,因此a[$0]=0++运算符的特性是先取值,后加1,因此Pattern等价于!0

  2,而0为假,!为取反,因此整个Pattern最后的结果为1,相当于if(1)Pattern匹配成功,输出当前记录,对于dup文件,前3条记录的处理方式都是如此。

3,当读取第4行数据“hello world”的时候,a[$0]=1,取反后的结果为0,即Pattern0Pattern匹配失败,因此不输出这条记录,后续的数据以此类推,最终成功实现去除文件中的重复行。

 

--------=====--------

 

posted @ 2018-07-03 11:28  虫儿要吃草  阅读(208)  评论(0编辑  收藏  举报