shell编程-大杂烩

shell学习

不退出vim执行

::!bash change_ip.sh 10.190.172.6 10.190.172.7  

                           VIM中执行Shell命令,有以下几种形式:

1.  :!command

    不退出vim,并执行shell命令command,将命令输出显示在vim的命令区域,不会改变当前编辑的文件的内容  例如::!ls -l如果你正在编辑一个脚本,vim ErrorMail.sh,代码基本写完,你想测试一下你不用保存退出,你可以先保存 :w! 然后再执行这个脚本  :!sh ErrorMai.sh.此时你并没有退出vim编辑器,返回结果后,你只要回车一下可以继续编辑

2. :r!command

   shell命令command的结果插入到当前行的下一行.例如::r!date,读取系统时间并插入到当前行的下一行。

3.  :起始行号,结束行号 !command

   将起始行号和结束行号指定的范围中的内容输入到shell命令command处理,并将处理结果替换起始行号和结束行号指定的范围中的内容.例如:62,72 !sort,将62行到72行的内容进行排序,可以只指定起始行,例如:62 !tr [a-z] [A-Z],将62行的小写字母转为大写字母

                                                                                                                    

linux shell 脚本输入参数解析

#!/bin/bash

para="para: ";

while [ $# -ge 2 ] ; do

        case "$1" in

                --aa) para="${para} argument $1 = $2;"; shift 2;;

                --bb) para="${para} argument $1 = $2;"; shift 2;;

                *) echo "unknown parameter $1." ; exit 1 ; break;;

        esac

done

echo $para

./test.sh   --aa 123 --bb 456

Linux shell 变量的基本运算

数值作为常规变量直接赋值给变量,并且以字符串形式保存。

let 命令可以用于直接执行基本操作:

当我使用 let 的时候,我们不使用 $ 符号引用变量。

no1=7;

no2=8;

echo "------------ let command -------------"

let no1++;

let no2--;

let no1+=3;

let no2-=5;

let result=no1+no2;

printf "let result=%d\n" $result;

" [ ] "运算符跟 let 命令很相似:

"[ ]" 运算符里面可以使用 $ 符号引用变量,同时支持变量名与运算符之间不带空格。

echo "----------------- [] operator ----------------"

printf "no1:%d no2:%d \n" $no1 $no2;

result1=$[ no1 + no2 ];

printf "result1 = %d \n" $result1;

result2=$[no1+no2 + 7];

printf "result2 = %d \n" $result2;

result3=$[ $no1+$no2+5 ];

printf "result3 = %d \n" $result3;

no2=$[ no2 + 1 ];

printf "no1 = %d no2 = %d \n" $no1 $no2;

" (( )) " 运算符跟 " [ ] " 运算符一样:

同样支持使用 $ 符号引用变量进行基本运算,同时支持变量名与运算符之间不带空格。

echo "----------------- (( )) operator --------------"

printf "no1: %d no2: %d \n" $no1 $no2;

result1=$(( no1 + no2 ));

printf "result1 = %d \n" $result1;

result2=$((no1+no2+3));

printf "result2 = %d \n" $result2;

result3=$(( $no1+$no2 + 5))

printf "result3 = %d \n" $result3;

"expr" 命令同样可以用于变量的基本运算:

"expr" 命令同样支持 $ 符号引用变量进行基本运算,但是变量与运算符之间必须使用空格作为分隔符;

在使用 "expr" 命令对变量进行运算后,整个表达式必须使用 " · expression · " 的模式赋值给变量,即包含在 " ` " 符里面,

并且等效于 " $( expression ) " 模式。

echo "---------------- expr command ---------------"

printf "no1: %d no2: %d \n" $no1 $no2;

result1=`expr 3 + 4`;

printf "result1 = %d \n" $result1;

result2=`expr $no1 + 4`;

printf "result2 = %d \n" $result2;

result3=`expr $no1 + $no2`;

printf "result3 = %d \n" $result3;

result4=`expr $no1+$no2`;

printf "result4 = %d \n" $result4;

result5=$(expr $no1 + 3);

printf "result5 = %d \n" $result5;

result6=$(expr $no1+4);

printf "result6 = %d \n" $result6;

result7=$(expr $no1+$no2);

printf "result7 = %d \n" $result7;

" expr " 命令的表达式中,变量与运算符之间必须使用空格作为分隔符,

上面所述的四种shell中执行变量运算的方式中不支持浮点运算!

2, Linux shell 中使用 bc 命令实现高级数学运算:

bc有三个参数,scale是运算精度,ibase指定输入变量的记数进制;obase指定输出变量的记数进制;

bc 命令使用 标准输入 stdin 作为输入;

bc 是一个支持精确的浮点运算的高级计算器;

bc 拥有相当多的输入选项,并且支持数学函数调用;

执行 bc --help 自行查看 bc 所支持的输入选项;

2.1 bc 命令使用标准输入 stdin 作为输入,并且支持浮点运算:

echo "----------------- bc command ----------------"

echo "4 * 0.56" | bc;

no=48;

result1=`echo "$no * 1.5" | bc`;

echo "result1 = $result1";

2.2 bc 命令支持运算精度设置:

通过附加参数可以给 bc 指定运算精度;指定输入变量的记数进制;

附加参数使用分号 " ; " 作为分隔符;

result2=`echo "scale=9;$no / 3;" | bc`;

echo "result2 = $result2";

实验结果所示,使用分号 " ; " 加入附加参数 scale ,指定精度为 9 位小数;

2.3 使用 bc 进行数值的记数进制间转换:

通过 ibase=value 作为附加参数,指定输入变量的记数进制;

通过 obase=value 作为附加参数,指定输出变量的记数进制;

no=100;

echo "echo \"obase=2;ibase=10;$no\" | bc = `echo "obase=2;ibase=10;$no" | bc`";

no=1000;

echo "echo \"scale=5;obase=10;ibase=2;$no/3\" | bc = `echo "scale=5;obase=10;ibase=2;$no/3" | bc`";

2.4 使用 bc 调用数学公式进行高级数学运算:

" sqrt(value) " 执行 value 的开方运算;

" value^index " 执行 value 的幂运算;

echo "sqrt(100) = `echo "sqrt(100)" | bc`";

echo "sqrt(100) = $(echo "sqrt(100)" | bc)";

echo "10^3 = `echo "10^3" | bc`";

echo "10^3 = $(echo "10^3" | bc)";

Linux之awk内建数学函数之左移运算、右移运算、按位取反运算

位操作是程序设计中对位模式按位或二进制数的一元和二元操作。在许多古老的微处理器上,位运算比加减运算略快,通常位运算比乘除法运算要快很多。在现代架构中,情况并非如此:位运算的运算速度通常与加法运算相同(仍然快于乘法运算)。移位是一个二元运算符,用来将一个二进制数中的每一位全部都向一个方向移动指定位,溢出的部分将被舍弃,而空缺的部分填入一定的值。

程序设计中,位操作运算符的一种。在c++中,移位运算符有双目移位运算符:<<(左移)和>>(右移)。移位运算符组成的表达式也属于算术表达式,其值为算术值。左移运算是将一个二进制位的操作数按指定移动的位数向左移位,移出位被丢弃,右边的空位一律补0。右移运算是将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,左边移出的空位或者一律补0,或者补符号位,这由不同的机器而定。在使用补码作为机器数的机器中,正数的符号位为0,负数的符号位为1。

在移位运算时,byte、short和char类型移位后的结果会变成int类型,对于byte、short、char和int进行移位时,规定实际移动 的次数是移动次数和32的余数,也就是移位33次和移位1次得到的结果相同。移动long型的数值时,规定实际移动的次数是移动次数和64的余数,也就是 移动66次和移动2次得到的结果相同。

[root@Legion10 ~]# echo 233 | awk '{print lshift($1,5),rshift($1,5),$1}'

7456 7 233

[root@Legion10 ~]#

解析:

[root@Legion10 ~]# echo 233 | awk '{print lshift($1,5),rshift($1,5),$1}'

7456 7 233

[root@Legion10 ~]# cat 2

dec             bin             |       dec                     bin

233             0000011101001   |       233                     11101001

7456            1110100100000   |       7                       00000111

----左移5位-------------        |   ----右移5位------------

[root@Legion10 ~]#

Linux之awk内建数学函数之左移运算、右移运算、按位取反运算

来个右移位运算计算ip

[root@Legion10 ~]# echo 134744072|awk '{

    a=0xFF000000;

    b=0xFF0000;

    c=0xFF00;

    d=0xFF;

    e=rshift(and($1,a),24);

    f=rshift(and($1,b),16);

    g=rshift(and($1,c),8);

    h=and($1,d);

    printf("%d.%d.%d.%d\n",e,f,g,h)

}'

8.8.8.8

[root@Legion10 ~]#

Linux之awk内建数学函数之左移运算、右移运算、按位取反运算

bash脚本中没有移位运算符。不过可以借助awk脚本来实现。

比如对数字 N 右移3位

echo N | awk '{print rshift($0, 3)} '

又如,左移5位

echo N | awk '{print lshift($0, 5)} '

各种括号的作用()、(())、[]、[[]]、{}

小括号,圆括号()

单小括号 ()

   ①命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。

   ②命令替换。等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。有些shell不支持,如tcsh。

    ③用于初始化数组。如:array=(a b c d)

双小括号 (( ))

    ①整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是"假",而一个非零值的表达式所返回的退出状态码将为0,或者是"true"。若是逻辑判断,表达式exp为真则为1,假则为0。

    ②只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。如:echo $((16#5f)) 结果为95 (16进位转十进制)

    ③单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6

    ④常用于算术运算比较,双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in `seq 0 4`或者for i in {0..4}。再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。

中括号,方括号[]

单中括号 []

    ①bash 的内部命令,[和test是等同的。如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识,右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号,但是新版的Bash中要求必须这样。

    ②Test和[]中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq,-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用,对于字符串比较可以使用转义形式,如果比较"ab"和"bc":[ ab \< bc ],结果为真,也就是返回状态为0。[ ]中的逻辑与和逻辑或使用-a 和-o 表示。

    ③字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。

    ④在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号。

双中括号[[ ]]

    ①[[是 bash 程序语言的关键字。并不是一个命令,[[ ]] 结构比[ ]结构更加通用。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。

    ②支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。

    ③使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。

    ④bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。

例子:

    if ($i<5) 

    if [ $i -lt 5 ] 

    if [ $a -ne 1 -a $a != 2 ] 

    if [ $a -ne 1] && [ $a != 2 ] 

    if [[ $a != 1 && $a != 2 ]] 

    for i in $(seq 0 4);do echo $i;done 

    for i in `seq 0 4`;do echo $i;done 

    for ((i=0;i<5;i++));do echo $i;done 

    for i in {0..4};do echo $i;done 

大括号、花括号 {}

常规用法

    ①大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。第一种:对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。第二种:对大括号中以点点(..)分割的顺序文件列表起拓展作用,如:touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt

    # ls {ex1,ex2}.sh 

    ex1.sh  ex2.sh 

    # ls {ex{1..3},ex4}.sh 

    ex1.sh  ex2.sh  ex3.sh  ex4.sh 

    # ls {ex[1-3],ex4}.sh 

    ex1.sh  ex2.sh  ex3.sh  ex4.sh 

    ②代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格。

几种特殊的替换结构

${var:-string},${var:+string},${var:=string},${var:?string}

      ①${var:-string}和${var:=string}:若变量var为空,则用在命令行中用string来替换${var:-string},否则变量var不为空时,则用变量var的值来替换${var:-string};对于${var:=string}的替换规则和${var:-string}是一样的,所不同之处是${var:=string}若var为空时,用string替换${var:=string}的同时,把string赋给变量var: ${var:=string}很常用的一种用法是,判断某个变量是否赋值,没有的话则给它赋上一个默认值。

      ② ${var:+string}的替换规则和上面的相反,即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量 var的值,即空值。(因为变量var此时为空,所以这两种说法是等价的) 

      ③${var:?string}替换规则为:若变量var不为空,则用变量var的值来替换${var:?string};若变量var为空,则把string输出到标准错误中,并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。

      补充扩展:在上面这五种替换结构中string不一定是常值的,可用另外一个变量的值或是一种命令的输出。

四种模式匹配替换结构

模式匹配记忆方法:

# 是去掉左边(在键盘上#在$之左边)

% 是去掉右边(在键盘上%在$之右边)

#和%中的单一符号是最小匹配,两个相同符号是最大匹配。

${var%pattern},${var%%pattern},${var#pattern},${var##pattern}

     第一种模式:${variable%pattern},这种模式时,shell在variable中查找,看它是否一给的模式pattern结尾,如果是,就从命令行把variable中的内容去掉右边最短的匹配模式

     第二种模式: ${variable%%pattern},这种模式时,shell在variable中查找,看它是否一给的模式pattern结尾,如果是,就从命令行把variable中的内容去掉右边最长的匹配模式

     第三种模式:${variable#pattern} 这种模式时,shell在variable中查找,看它是否一给的模式pattern开始,如果是,就从命令行把variable中的内容去掉左边最短的匹配模式

     第四种模式: ${variable##pattern} 这种模式时,shell在variable中查找,看它是否一给的模式pattern结尾,如果是,就从命令行把variable中的内容去掉右边最长的匹配模式

     这四种模式中都不会改变variable的值,其中,只有在pattern中使用了*匹配符号时,%和%%,#和##才有区别。结构中的pattern支持通配符,*表示零个或多个任意字符,?表示仅与一个任意字符匹配,[...]表示匹配中括号里面的字符,[!...]表示不匹配中括号里面的字符。

    # var=testcase 

    # echo $var 

    testcase 

    # echo ${var%s*e}

    testca 

    # echo $var 

    testcase

    # echo ${var%%s*e}

    te

    # echo ${var#?e} 

    stcase

    # echo ${var##?e} 

    stcase

    # echo ${var##*e} 

    # echo ${var##*s} 

    e 

    # echo ${var##test} 

    case 

字符串提取和替换

${var:num},${var:num1:num2},${var/pattern/pattern},${var//pattern/pattern}

       第一种模式:${var:num},这种模式时,shell在var中提取第num个字符到末尾的所有字符。若num为正数,从左边0处开始;若num为负数,从右边开始提取字串,但必须使用在冒号后面加空格或一个数字或整个num加上括号,如${var: -2}、${var:1-3}或${var:(-2)}。        

        第二种模式:${var:num1:num2},num1是位置,num2是长度。表示从$var字符串的第$num1个位置开始提取长度为$num2的子串。不能为负数。

       第三种模式:${var/pattern/pattern}表示将var字符串的第一个匹配的pattern替换为另一个pattern。。        

       第四种模式:${var//pattern/pattern}表示将var字符串中的所有能匹配的pattern替换为另一个pattern。

[root@centos ~]# var=/home/centos

[root@centos ~]# echo $var

/home/centos

[root@centos ~]# echo ${var:5}

/centos

[root@centos ~]# echo ${var: -6}

centos

[root@centos ~]# echo ${var:(-6)}

centos

[root@centos ~]# echo ${var:1:4}

home

[root@centos ~]# echo ${var/o/h}

/hhme/centos

[root@centos ~]# echo ${var//o/h}

/hhme/cenths

符号$后的括号

(1)${a} 变量a的值, 在不引起歧义的情况下可以省略大括号。

(2)$(cmd) 命令替换,和`cmd`效果相同,结果为shell命令cmd的输,过某些Shell版本不支持$()形式的命令替换, 如tcsh。

(3)$((expression)) 和`exprexpression`效果相同, 计算数学表达式exp的数值, 其中exp只要符合C语言的运算规则即可, 甚至三目运算符和逻辑表达式都可以计算。

使用

1、多条命令执行

(1)单小括号,(cmd1;cmd2;cmd3) 新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。

(2)单大括号,{ cmd1;cmd2;cmd3;} 在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开。

对{}和()而言, 括号中的重定向符只影响该条命令, 而括号外的重定向符影响到括号中的所有命令。

解决Linux系统中出现You have new mail in /var/spool/mail/root的问题

第一步

关闭提示

echo "unset MAILCHECK">> /etc/profile

source /etc/profile

第二步

查看

ls -lth /var/spool/mail/

清空

cat /dev/null > /var/spool/mail/root

2>&1表示,我把错误输出重定向到标准屏幕输出1上,在赋值给变量aa

echo "errormsg" >&2; 标准错误

echo "infomsg" >&1; 标准输出

cat一个不存在的文件,会有错误输出,我可以把错误重定向到文件里

用管道符'>'重定向标准错误输出:

#cat /tmp/aa

cat: /tmp/aa: No such file or directory

#cat /tmp/aa 2>err.log

#cat err.log

cat: /tmp/aa: No such file or directory

Shell中 &>/dev/null和 >/dev/null 2>&1

将脚本的主体包装在大括号中并重定向到/ dev / null:

#!/usr/bin/ksh

{

for i in *.DAT

do

    awk 'BEGIN{OFS=FS=","}$3~/^353/{$3="353861958962"}{print}' $i >> $i_changed

    awk '$3~/^353/' $i_changed >> $i_353

    rm -rf $i_changed

done

} >/dev/null 2>&1

这也会将错误发送到比特桶.这可能不是一个好主意;如果您不想这样,请删除2>& 1重定向.

另外:注意 – 您可能需要使用${i} _changed和${i} _353.这就是为什么输出不会转到文件…你的变量${i_changed}和${i_353}没有初始化,因此重定向不命名文件.

文件描述符

文件描述符是与文件输入、输出关联的整数。它们用来跟踪已打开的文件。最常见的文件描述符是stidin、stdout、和stderr。我们可以将某个文件描述符的内容重定向到另外一个文件描述符中。

文件描述符我们常见的就是系统预留的0,1和2这三个,他们的意义分别有如下对应关系:

0 —— stdin(标准输入)

1 —— stdout (标准输出)

2 —— stderr (标准错误)

关于如何调试shell脚本

#sh -vx xxxx.sh

echo命令

printf 'a%.0s' {1..100}

 

echo命令用于在shell中打印shell变量的值,或者直接输出指定的字符串。linux的echo命令,在shell编程中极为常用, 在终端下打印变量value的时候也是常常用到的,因此有必要了解下echo的用法echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作 用。

语法

echo(选项)(参数)选项

-e:激活转义字符。使用-e选项时,若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:

?\a 发出警告声;

?\b 删除前一个字符;

?\c 最后不加上换行符号;

?\f 换行但光标仍旧停留在原来的位置;

?\n 换行且光标移至行首;

?\r 光标移至行首,但不换行;

?\t 插入tab;

?\v 与\f相同;

?\ 插入\字符;

?\nnn 插入nnn(八进制)所代表的ASCII字符;

用echo命令打印带有色彩的文字:

其中“F“为字体颜色,编号为30-37,“B”为背景颜色,编号为40-47。颜色表如下

F       B

30      40      黑色

31      41      红色

32      42      绿色

33      43      黄色

34      44      蓝色

35      45      紫红色

36      46      青蓝色

37      47      白色

文字色:

echo -e "\e[1;31mThis is red text\e[0m"

This is red text?\e[1;31m 将颜色设置为红色

?\e[0m 将颜色重新置回

颜色码:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37

背景色:

echo -e "\e[1;42mGreed Background\e[0m"

Greed Background颜色码:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47

文字闪动:

echo -e "\033[37;31;5mMySQL Server Stop...\033[39;49;0m"

红色数字处还有其他数字参数:0 关闭所有属性、1 设置高亮度(加粗)、4 下划线、5 闪烁、7 反显、8 消隐

echo -n 不换行输出

echo -e 处理特殊字符

若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:

\a 发出警告声;

\b 删除前一个字符;

\c 最后不加上换行符号;

\f 换行但光标仍旧停留在原来的位置;

\n 换行且光标移至行首;

\r 光标移至行首,但不换行;

\t 插入tab;

\v 与\f相同;

\ 插入\字符;

\nnn 插入nnn(八进制)所代表的ASCII字符;

举例说明:

$echo -e "a\bdddd"  //前面的a会被擦除

$echo -e "a\adddd" //输出同时会发出报警声音

$echo -e "a\ndddd" //自动换行

我们在使用linux的过程中,经常会去下载安装包,下载时候的那个进度提示是不是比较好玩,下载进度的百分比在不断变化,利用echo -e和-n参数我们也可以实现这个效果了。

脚本的基本结构

一个脚本的基本结构是这样的:

#!SHEBANG

CONFIGURATION_VARIABLES

FUNCTION_DEFINITIONS

MAIN_CODE

Shebang

如果可能,请不要忘记shebang。

请小心使用/bin/sh作为shebang,在Linux系统中,/bin/sh就是Bash这是一个错误的观点。

于我而言,shebang有两个目的:

说明直接执行时以哪个解释器来执行;

明确该脚本应该以哪个解释器来执行;

命令替换

正如文章the article about command substitution [Bash Hackers Wiki]中提及的,你应该使用$( .. )形式。

不过,如果可移植性是一个问题,你可能必须使用反引号的形式...。

在任何情况,如果其它展开或者单词分隔并不是你期望的,你应该将命令替换用双引号引起来。

环境变量

变量:全部是大写字母

变量引用:全部以变量名加双引号引用,如”$TERMTYPE”,或“${TERMTYPE}”,如果变量类型是数值型不引用,如:

如果需要从配置文件导出变量,则在变量前加一大写字母,以识别导出变量与自定义环境变量的区别,如:

变量值的引用尽量以$开头,如$(ls inst_.sh),避免使用`ls inst_。sh`

循环控制变量可以命名为单个字母, 比如 i、j等。 也可以是更有意义的名称, 比如 UserIndex。

环境变量和全局变量 在脚本开头定义。

函数中使用较多的文件,以环境变量的形式在文件开头定义,仅函数中使用的变量在函数开头定义

配置变量

在这里,我将这一类变量——可以被用户更改的——叫做配置变量。

让这类变量容易找到,一般放在脚本的头部,给它们有意义的名称并且加上注释说明。正如上面说的,仅当你知道你为什么这么做的时候,才用大写的变量名形式,否则小写形式更加安全。

语句

if 语句

if/then/else 语句中最可能被执行的部分应该放在 then 子句中, 不太可能被执行的部分应该放在 else 子句中。

如果可能, 尽量不要使用一连串的 if 语句, 而应该以 case 语句替代。

不要使 if 语句嵌套超过5层以上, 尽量以更清楚的代码替代。

case 语句

概要

case 语句中的单个子句应该以 case 常数的数字顺序或字母顺序排列。 子句中的执行语句应该尽量保持简单, 一般不要超过4到5行代码。 如果执行语句过于复杂, 应该将它放置在独立的函数中。

case 语句的 *) 子句应该只在正常的默认情况或检测到错误的情况下使用。

格式

case 语句遵循同样的缩进和命名约定。

while 语句

使用 Exit 过程退出 while 循环是不好的; 如果可能, 应该只使用循环条件来结束循环。

while 循环的所有初始化代码应该紧贴在进入 while 循环之前, 不要被其他无关语句分隔开。

循环结束后的处理应该紧跟在循环之后。

for 语句

如果需要执行确定次数的增量循环, 应该用 for 语句替代 while 语句。

参数展开

除非你知道自己做的事情,请在参数展开的地方使用双引号

当然,也有一些地方并不需要使用双引号,例如:

[[ ]]测试表达式内部是不会展开的;

在case $WORD in语法中WORD也不会展开的;

在变量赋值var=$WORD的地方也是不会展开的 但是在这些地方使用引号并不会出错,如果你习惯于在每个可能展开参数的地方使用引号,你写得代码会很安全。

如果你要传递一个参数作为一个单词列表,你可以不使用引号,例如:

list="one two three"

# you MUST NOT quote $list here

for word in $list; do

  ...

done

分离复合命令

译者注:其实这里的复合命令就是指块语句,例如for/while循环, if分支结构等等。

HEAD_KEYWORD parameters; BODY_BEGIN

  BODY_COMMANDS

BODY_END

我习惯于:

将HEAD_KEYWORD和初始化命令或者参数放在第一行;

将BODY_BEGIN同样放在第一行;

复合命令中的BODY部分以2个空格缩进;

BODY_END部分独立一行放在最后;

1)if/then/elif/else分支语句

if ...; then

  ...

elif ...; then

  ...

else

  ...

fi

2)for循环

for f in /etc/*; do

  ...

done

3) while/until循环

while [[ $answer != [YyNn] ]]; do

  ...

done

4) case分支语句

case $input in

  hello)

    echo "You said hello"

  ;;

  bye)

    echo "You said bye"

    if foo; then

      bar

    fi

  ;;

  *)

    echo "You said something weird..."

  ;;

esac

几点注意的地方:

如果不是100%需要,匹配部分左右的括号不需要写(译者注:例如写成hello)而不是(hello));

匹配模式与分支的终止符号;;位于同一缩进级别

分支内部的命令多缩进一层;

尽管是可选的,这里还是把最后一个分支的终止符号也写上了;

分隔长行

每行不要超过80字,如果超出,建议用“\”折行,有管道的命令行除外。

如果需要分隔过长的代码,你可以使用下面的任意一种方法:

1) 使用与命令宽度相同的缩进

activate some_very_long_option \

         some_other_option

2) 使用2个空格缩进

activate some_very_long_option \

  some_other_option

从个人的角度来说,除非有特别的需要,我更倾向于第一种形式,因为它突出“上下两行的内容是一起的”这一联系。

缩进

由于Shell没有很好的编辑环境,所以,建议用四个空格为基数进行缩进,好处在不同的环境下TAB可能代表的空格数不同,造成代码的错乱。用TAB他的优点是速度快方便,可以在编辑的时候也用TAB,但需要转换。

可以在更改编辑器,Windows的就不说了,主要是VIM

:set softtabstop=4

注意不要使用 :set tabstop=4 上面那个是同时把这一个TAB转换为四个空格,而这一条是定义TAB为四个空格,如果到其它编辑器上就会看到默认8个空格的情况,那就会不美观了。

另外将原有的TAB转换为空格,:retab

如果想让刚才的配置永久生效需要改动vim的配置文件 vim ~/.vimrc,更多详细的有用的配置见“VIM配置总结”

代码开头约定

1、第一行一般为调用使用的语言

2、下面要有这个程序名,避免更改文件名为无法找到正确的文件

3、版本号

4、更改后的时间

5、作者相关信息

6、该程序的作用,及注意事项

7、版权与是否开放共享GNU说明

函数约定

函数名称应该采用小写的形式,并且有一个很好的意义。函数名称应该容易让人理解,比如f1这个名称虽然容易输入但是对调试和其它人阅读代码造成了很大的困难,它说明不了任何东西。好的函数名称可以帮助说明代码,而不需要额外的注释。

一个或多或少有趣的是:如果你无意这样做,不要把函数名称命名为常见的命令名,新手往往比较容易将脚本或者函数名命名成test,这样就和UNIX的test命令冲突了。

除非绝对必要,仅使用字母、数字和下划线作为函数名称。

每个函数控制在50-100行,超出行数建议分成两个函数

多次反复调用的程序最好分成函数,可以简化程序,使程序条理更清楚

所有函数定义应该在脚本主要代码执行之前,这样可以给人全局的印象,并且确保所有函数在使用之前它是已知的。

你应该使用可移植性高的函数定义形式,即不带function关键字的形式。

关于注释

程序头应加注版本与功能说明的注释。但程序第一行不能汉字。

程序体中应包含必要的注释,注释说明如下:

单行注释,可以放在代码行的尾部或代码行的上部;

多行注释,用于注解复杂的功能说明,可以放在程序体中,也可以放在代码块的开始部分

代码修改时,对修改的内容要加必要版本注释及功能说明。

命名约定

1.本文档的命名约定是系统配置文件、脚本文件;

2.文件名、变量名、函数名不超过20个字符;

3.命名只能使用英文字母,数字和下划线,只有一个英文单词时使用全拼,有多个单词时,使用下划线分隔,长度较长时,可以取单词前3~4个字母。

4.文件名全部以小写命名,不能大小写混用(通过U盘交换文件时,大小写可能会丢失,即:大写文件名可能会全部变成小写文件名);

5.避免使用Linux的保留字如true、关键字如PWD等(见附表);

远程shell

ssh免密

sshd为了安全,对属主的目录和文件权限有所要求。如果权限不对,则ssh的免密码登陆不生效。

                用户目录权限为 755 或者 700,就是不能是77x。

                .ssh目录权限一般为755或者700。

                rsa_id.pub 及authorized_keys权限一般为644

                rsa_id权限必须为600

查看目录属性 

ls -ld    directoy

文件的默认权限

umask               显示系统预留权限值

vim /etc/bashrc           71行是普通用户的更改,73是超级用户的更改

vim /etc/profile           60行是普通用户的更改,62是超级用户的更改

source /etc/bashrc        刷新bash配置

source /etc/profile        刷新系统配置

6.特殊权限

stickyid         强制位

o+t                 之针对目录,当一个目录上有t权限时,这个目录中的文件只能被文件拥有者删除

t=1

chmod o+t directroy

chmod 1777 directory

sgid             粘制位

g+s            针对目录,在目录中创建的文件都自动归属到目录所在组,针对二进制文件,

文件内记录的程序在执行时和执行者的组身份没有关系,而是以二进制文件的所有组的身份执行的

chmod g+s file|directory

chmod 2777 file|directory

suid            冒险位

u+s             针对文件,文件记录动作在执行时是一文件所有人身份执行的,与是谁发起的无关

chmod u+s file

chmod 4777 fileg+s

7.权限列表

   *1.acl                 指定特定的用户对特定的文件拥有特殊权力

-rw-rwx---+ 1    root    root 0 Mar 28 02:39 file

d rwx  rwx  rwx  =777  表示目录的操作权限

-  rwx  rwx  rwx = 777  表示文件的操作权限

printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg

printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234

%s %c %d %都是格式替代符

%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充

,超过也会将内容全部显示出来。

%-4 2f 指格式化小数,其中,.2指保留2为小数

命令行执行登录并且在目标服务器上执行命令

ssh user@remoteNode "cd /home ; ls"  

  1. 双引号,必须有。如果不加双引号,第二个ls命令在本地执行
  2. 分号,两个命令之间用分号隔开

脚本的方式 

这个正式我想要的方式,在目标服务器上执行批量的命令。

#!/bin/bash  

ssh root@fusion1   << remotessh  

ll 

exit  

remotessh  

远程执行的内容在“<< remotessh ” 至“ remotessh ”之间,在远程机器上的操作就位于其中,注意的点:<< remotessh,ssh后直到遇到remotessh这样的内容结束,remotessh可以随便修改成其他形式。在结束前,加exit退出远程节点

如果不想日志文件在本机出现可以修改配置 

  1. ssh [email protected] > /dev/null 2>&1   << remotessh  

grep对匹配结果取反: grep -v "pattem" file > file2。

linux 获取网卡信息

sar -n DEV 2

IFACE:LAN接口

rxpck/s:每秒钟接收的数据包

txpck/s:每秒钟发送的数据包

rxbyt/s:每秒钟接收的字节数

txbyt/s:每秒钟发送的字节数

rxcmp/s:每秒钟接收的压缩数据包

txcmp/s:每秒钟发送的压缩数据包

rxmcst/s:每秒钟接收的多播数据包

sar –n DEV 1 2

命令后面1 2 意思是:每一秒钟取1次值,取2次。

DEV显示网络接口信息

另外,有6个不同的开关:DEV | EDEV | NFS | NFSD | SOCK | ALL ,其代表的含义如下:

 ● DEV显示网络接口信息。

● EDEV显示关于网络错误的统计数据。

● NFS统计活动的NFS客户端的信息。

● NFSD统计NFS服务器的信息

● SOCK显示套接字信息

● ALL显示所有5个开关

sed

删除最后一行

sed -i '$d' fileName

删除以zx开头,以add结尾的行:

sed  '/^zx/{/add$/d}'   /etc/sudoers

zx  ALL=(ALL) NOPASSWD: /usr/sbin/useradd 被删除

1、删除文档的第一行

sed -i '1d'

2、删除文档的最后一行

sed -i '$d'

3、删除文件中的一行

sed -i '3d'

4、删除文件中包含某个关键字开头的所有行

sed -i '/^QWQ/d'

5、删除文件中包含某个关键字的所有行 

sed -i '/QWQ/d'

Linux之使用sed取出IP地址

//匹配IP地址

ip addr|sed -nr 's#^.*inet (.*)/24.*$#\1#gp'

ip addr|awk -F '[ /]+' 'NR==9 {print $3}'

//对调用户名,登录权限

cat /etc/passwd|sed -nr 's#([^:]+)(:.*:)(/.*)#\3\2\1#gp'

可使用分号隔开多个命令

sed -i '4d;5d;56d;78d;82d' abc.txt

awk '{for(i=1;i<=NF;++i) printf $i "\t";printf "\n"}' test.txt

awk '{ $3=""; print $0 }'   a.txt

将某列置为空,然后打印所有列。

截取第二行:

ifconfig |sed -n '2p'

sed 批量替换多个文件内容

平常需要替换多个文件里的内容,通过sed命令就可以很方便的替换。

sed -i “s/原字符串/新字符串/g”  `grep  -rl 原字符串 所在目录`

解释:

1. sed -i  :  直接替换文件内容。

2. sed ‘s/要被取代的字串/新的字串/g’ 这种模式是一种替换模式,但是这样是直接输出,不会修改文件;要修改文件,需要加上-i.

3. grep -r 搜索子目录查找, -l 表示输出匹配到的文件名。

4. 反引号“ ,是将里面的字符串当做命令执行。

例子: 替换h目录所有文件的listen  ,替换为:listen_new

sed -i ‘s/listen/listen_new/g’  `grep -rl listen  ./h/*`

数组

个数:${#OLD_IPS[@]}

获取字符串的长度:

       str="hello"

       len=${#str}

1、获取数组元素的个数:

        array=(bill   chen  bai   hu);

        num=${#array[@]}                          //获取数组元素的个数。

       遍历数组就变成非常简单的事情:

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

       {

                         echo   $array[i];

       }

       获取数组某一个单元的长度就变成了:

       ${#array[i]}

2、获取数组的所有元素:

      ${array[*]}

     遍历数组就编程了非常简单的事情:

     for var in  ${array[*]}

     do

                  echo $var;

     done

     获取数组某一个单元的长度就变成了:

     ${#var}

linux下的shell运算(加、减、乘、除

2018年06月17日 16:03:58 hxpjava1 阅读数 25917

((i=$j+$k))    等价于 i=`expr $j + $k`

((i=$j-$k))     等价于   i=`expr $j -$k`

((i=$j*$k))     等价于   i=`expr $j \*$k`

((i=$j/$k))     等价于   i=`expr $j /$k`

Let expressions 执行一个或多个表达式。表达式中的变量前不必有$.如果表达式中包含了空格或其他特殊字符,则必须引起来。

例:let “I = I + 1” 或 let i=i+1

算术运算符指的是可以在程序中实现加、减、乘、除等数学运算的运算符。Shell中常用的数学运算符如下所示。

— +:对两个变量做加法。

— -:对两个变量做减法。

— *:对两个变量做乘法。

— /:对两个变量做除法。

— **:对两个变量做幂运算。

— %:取模运算,第一个变量除以第二个变量求余数。

— +=:加等于,在自身基础上加第二个变量。

— -=:减等于,在第一个变量的基础上减去第二个变量。

— *=:乘等于,在第一个变量的基础上乘以第二个变量。

— /=:除等于,在第一个变量的基础上除以第二个变量。

— %=:取模赋值,第一个变量对第二个变量取模运算,再赋值给第一个变量。

在使用这些运算符时,需要注意到运算顺序的问题。例如输入下面的命令,输出1+2的结果。

echo 1+2

Shell并没有输出结果3,而是输出了1+2。在shell中有三种方法可以更改运算顺序。

— 用expr改变运算顺序。可以用echo `expr 1 +2`来输出1+2的结果,用expr表示后面的表达式为一个数学运算。需要注意的是,`并不是一个单引号,而是“Tab”键上面的那个符号。

— 用let指示数学运算。可以先将运算的结果赋值给变量b,运算命令是b=let 1 + 2。然后用echo$b来输出b的值。如果没有let,则会输出1+2。

— 用$[]表示数学运算。将一个数学运算写到$[]符号的中括号中,中括号中的内容将先进行数学运算。例如命令echo$[1+2],将输出结果3。

下面是一个shell程序实例,实现数学函数S=3(xy)+4x2+5y+6的运算。在程序中以位置变量的方式输入x与y的值。程序的编写步骤如下所示。

 在主菜单中打开一个终端。在终端中输入“vim”命令打开VIM。

 在VIM中按“i”键进入插入模式,然后输入下面的代码。

代码4-2  数学运算实例:\源文件\04\4.4.sh

#!/bin/bash

#4.4.sh

s=0                                    #定义一个求和变量,初值为0。

t=`expr$1**$2`                        #用expr改变运算顺序,求x的y次方。

t=$[t*3]                               #t乘以3。

s=$[s+t]                               #结果相加。

t=$[$1**2]                             #求x的平方。

t=$[t*4]                               #结果乘以4。

s=$[s+t]                               #结果相加。

t=`expr$2*5`                          #求5y的值。

s=$[s+t]                               #结果相加。

s=$[s+6]                               #结果加上6。

echo$s                                #输出结果。

echo$((a%b))                          #取余

 在这个程序中,需要注意算术运算的写法。如果没有expr或$[]更改运算顺序,则会将运算式以字符串的形式赋值,而不会赋值运算结果。

 按“Esc”键返回到普通模式。然后输入“:w 4.4.sh”保存文件。

 输入“:q”命令,按“Enter”键退出VIM。

 在终端中,输入下面的命令对4.4.sh文件添加可执行权限。

chmod +x 4.4.sh

 输入下面的命令运行程序。在命令中需要输入两个参数。

./4.4.sh 2 4

 程序会完成S=3(xy)+4x2+5y+6的数学运算并输出结果,结果如下所示。

90

#!/bin/bash
a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]
then
   echo "a is equal to b"
fi
if [ $a != $b ]
then
   echo "a is not equal to b"
fi

ip地址的组成(网络位+主机位)

IP地址采用分层结构;

IP地址是由网络号(net ID)与主机号(host ID)两部分组成的。

根据不同的取值范围,IP地址可以分为五类;IP地址中的前5位用于标识IP地址的类别:

     A类地址的第一位为0;

     B类地址的前两位为10;

     C类地址的前三位为110;

     D类地址的前四位为1110;

     E类地址的前五位为11110。

实际大多通过子网掩码来区分网络位和主机位,子网掩码跟IP地址一一对应,子网掩码为1的是网络位,为0的是主机位。

如:192.168.1.2 掩码255.255.255.0 。网络位192.168.1 主机位是2

举个例子:比如172.16.2.160/255.255.255.0

这个IP地址的【网络号】就是172.16.2.0 主机号为   0.0.0.160 

划分子网情况

如:172.16.2.160/255.255.255.192(IP地址/掩码)

1010   1100   0001   0000   0000   0010   1010   0000   (二进制)

1111    1111   1111    1111    1111    1111    1100   0000  (子网掩码)

------------------------------------------相"与"(理解成相乘)

1010   1100   0001   0000   0000   0010   1000   0000(172.16.2.128这就是子网号)

1010   1100   0001   0000   0000   0010   1000   0001(172.16.2.129是第一个主机)

1010   1100   0001   0000   0000   0010   1011   1110(172.16.2.190最后一个主机)

1010   1100   0001   0000   0000   0010   1011   1111   广播地址  172.16.2.191  

子网掩码的作用:

1,将一类ip地址(也就是只确定的网络号的ip)划分为更加小的子网络

(通常得到一个c类ip,如:212.26.220.0最后一组是主机号(最大255),用子网掩码分成更小的网段)

因为掩码的值是连续的1,那么子网掩码的值也就是有规律的:

比如

1000 0000 ---> 128

1100 0000 ---> 192

1110 0000 ---> 224

1111 0000 ---> 240

1111 1000 ---> 248

1111 1100 ---> 252

1111 1110 ---> 254

2,将相邻的网络地址合并成同一逻辑网络比如:

两个C类IP地址215.60.30.0与215.60.31.0与子网掩码255.255.254.0

11010111.00111100.00011110.00000000-->215.60.30.0

11010111.00111100.00011111.00000000-->215.60.31.0

11111111.11111111.11111110.10000000-->255.255.254.0//掩码

11010111.00111100.00011110.00000000-->215.60.30.0//都是该网段

注意:一个错误的理解:子网掩码主要目的是增加了ip数量!!!其实并没有增加!!!

          (也不能说没有增加,比如相同的ip不同子网掩码,实际公网是不存在相同的ip,,如果说是两个局域网这种情况,不知道算不算增加了)

补充:

1,只知道ip地址那么只能知道是属于哪一类ip。或者认为没有子网络,比如c类ip,那么前3组是网络号,后面一组是主机号

2,只有知道子网掩码和ip,才能知道具体的网段和主机号

3,相同子网掩码未必是同一网段ip,同一网段的ip必然有相同的子网掩码

 “IP地址/ 数字” 是什么意思?例如 192.168.5.12 / 21

数字是子网掩码位(数),说明子网掩码由21个1组成,即 子网掩码是:

11111111 11111111 11111000 00000000  ,也就是255.255.248.0.

两个数相加:

#!/bin/bash
val=`expr 2 + 2`

grep过滤IP

grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]"

grep -E  "([0-9]{1,3}\.){3}[0-9]"

grep -E  "([0-9]{1,3}\.){3}[0-9]" secure 

# echo "--999999999999999999999999" | egrep "-" –color

shell学习30:if判断中各种(-a到-z)选项的意思

[ -a FILE ]  如果 FILE 存在则为真。 

[ -b FILE ]  如果 FILE 存在且是一个块特殊文件则为真。 

[ -c FILE ]  如果 FILE 存在且是一个字特殊文件则为真。 

[ -d FILE ]  如果 FILE 存在且是一个目录则为真。 

[ -e FILE ]  如果 FILE 存在则为真。 

[ -f FILE ]  如果 FILE 存在且是一个普通文件则为真。 

[ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。 [ -h FILE ]  如果 FILE 存在且是一个符号连接则为真。 

[ -k FILE ]  如果 FILE 存在且已经设置了粘制位则为真。 

[ -p FILE ]  如果 FILE 存在且是一个名字管道(F如果O)则为真。 

[ -r FILE ]  如果 FILE 存在且是可读的则为真。 

[ -s FILE ]  如果 FILE 存在且大小不为0则为真。 

[ -t FD ]  如果文件描述符 FD 打开且指向一个终端则为真。 

[ -u FILE ]  如果 FILE 存在且设置了SUID (set user ID)则为真。 

[ -w FILE ]  如果 FILE 如果 FILE 存在且是可写的则为真。 

[ -x FILE ]  如果 FILE 存在且是可执行的则为真。 

[ -O FILE ]  如果 FILE 存在且属有效用户ID则为真。 

[ -G FILE ]  如果 FILE 存在且属有效用户组则为真。 

[ -L FILE ]  如果 FILE 存在且是一个符号连接则为真。 

[ -N FILE ]  如果 FILE 存在 and has been mod如果ied since it was last read则为真。 

[ -S FILE ]  如果 FILE 存在且是一个套接字则为真。 

[ FILE1 -nt FILE2 ]  如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。 

[ FILE1 -ot FILE2 ]  如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。 

[ FILE1 -ef FILE2 ]  如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。 

[ -o OPTIONNAME ]  如果 shell选项 “OPTIONNAME” 开启则为真。 

[ -z STRING ]  “STRING” 的长度为零则为真。 

[ -n STRING ] or [ STRING ]  “STRING” 的长度为非零 non-zero则为真。 

[ STRING1 == STRING2 ]  如果2个字符串相同。 “=” may be used instead of “==” for strict POSIX compliance则为真。 

[ STRING1 != STRING2 ]  如果字符串不相等则为真。

[ STRING1 < STRING2 ]  如果 “STRING1” sorts before “STRING2” lexicographically in the current locale则为真。 

[ STRING1 > STRING2 ]  如果 “STRING1” sorts after “STRING2” lexicographically in the current locale则为真。 

[ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.

=====================================================================

基本上和其他脚本语言一样。没有太大区别。不过值得注意的是。[]里面的条件判断。

1、字符串判断

str1 = str2      当两个串有相同内容、长度时为真

str1 != str2      当串str1和str2不等时为真

-n str1        当串的长度大于0时为真(串非空)

-z str1        当串的长度为0时为真(空串)

str1           当串str1为非空时为真

2、数字的判断

int1 -eq int2    两数相等为真

int1 -ne int2    两数不等为真

int1 -gt int2    int1大于int2为真

int1 -ge int2    int1大于等于int2为真

int1 -lt int2    int1小于int2为真

int1 -le int2    int1小于等于int2为真

3、文件的判断

-r file     用户可读为真

-w file     用户可写为真

-x file     用户可执行为真

-f file     文件为正规文件为真

-d file     文件为目录为真

-c file     文件为字符特殊文件为真

-b file     文件为块特殊文件为真

-s file     文件大小非0时为真

-t file     当文件描述符(默认为1)指定的设备为终端时为真

4、复杂逻辑判断

-a         与

-o        或

!        非

结尾

语法虽然简单,但是在SHELL里使用的时候,他的功能变得强大了。

Linux 下查看局域网内所有主机IP和MAC

sed的正则匹配

正则匹配IP和子网掩码

 [root@localhost log]#  ifconfig |sed -n '2p'

      [root@localhost log]# ifconfig |sed -n '2p' | sed -r 's#.*r:(.*) B.*k:(.*)#\1 \2#g'

      (.*)表示匹配的项,之后可以用\1取出第一个括号内匹配的内容,\2取出第二个括号内匹配的内容 

sed

# STR="MAIL FROM(CCC) TO(DDD)"

#echo $STR | sed -n 's/.*FROM([)]{1,}[)]{1,}).*TO(.∗.∗)/\1-\2/g'p

提取括号里面的内如

STR="MAIL FROM(ABCD) BODY"

echo $STR | sed 's/^.*FROM(.∗.∗).*$/\1/g'      # ABCD

STR="MAIL FROM(AB)CD) BODY"

echo $STR | sed 's/^.*FROM([)]\+[)]\+).*$/\1/g'        # AB

提取第一个括号和第二个括号里面的内如

STR="MAIL FROM(ABCD) TO(EFGH) BODY"

echo $STR | sed 's/^.*FROM([)]\+[)]\+).*TO([)]\+[)]\+).*$/\1-\2/g'         # ABCD-EFGH

猜你喜欢

转载自www.cnblogs.com/liuhongru/p/11402010.html