shell基本语法

随机数

echo $RANDOM |md5sum |cut -c 1-8

运算符

整数:
    方法1:
   a
=$[1+3] echo $a
   方法2:
   #!/bin/bash val=`expr 2 + 2` echo "两数之和为 : $val"
浮点数: 方法1: a=`echo "20 20 100"|awk '{printf("%g",$1*$2/$3)}'` echo $a 方法2: echo "scale=1; 2.5*4" | bc

详细请查看: http://www.runoob.com/linux/linux-shell-basic-operators.html (算术运算符、关系运算符、布尔运算符、逻辑运算符、字符串运算符、文件测试运算符)

 数组

例1. 数组赋值和显示,增加数组元素 ,显示数组个数
    [root@aming shellDir]# a=(1 2 3 4)      数组赋值
    [root@aming shellDir]# echo ${#a[*]}
    1 2 3 4
例2.显示数组第一个
    [root@aming shellDir]# echo ${a[0]}
    1
例3.增加数组元素
    [root@aming shellDir]# a[4]=9
例4.显示数组所有值
    [root@aming shellDir]# echo ${a[@]}
    1 2 3 4 9
例5.显示数组个数
    [root@aming shellDir]# echo ${#a[*]}
    5
例6.数组清楚某位
    [root@aming shellDir]# echo ${a[*]}
    1 2 3 4 9
    [root@aming shellDir]# unset a[2]
    [root@aming shellDir]# echo ${a[*]}
    1 2 4 9
例7.数组切片显示
    [root@aming shellDir]# echo ${a[*]}
    1 2 4 9
    [root@aming shellDir]# echo ${a[*]:0:2}          :0第几个索引   :2显示位数
    1 2
例8.  数组随机赋值,显示排序
    [root@aming shellDir]# cat 3arry.sh
    #!/bin/bash
    ##
    ##
    for i in `seq 0 9`
    do
            a[$i]=$RANDOM
    done
    echo ${a[*]}
    echo ${a[*]} | sed "s/ /
/g" | sort -n
    [root@aming shellDir]# sh 3arry.sh
    5177 13327 606 685 26238 24009 28414 8994 17346 5379
    606
    685
    5177
    5379
    8994
    13327
    17346
    24009
    26238
    28414

例子9.冒泡排序
    [root@aming shellDir]# cat 3arry.sh
    #!/bin/bash
    for i in `seq 0 9`
    do
            a[$i]=$RANDOM
    done
    echo ${a[*]}
    t=0
    for i in `seq 0 9`
    do
            num=$[8-$i]
            for j in `seq 0 $num`
                    do
                    c=$[$j+1]
                    if [ ${a[$j]} -gt ${a[$c]} ]
                            then
                            t=${a[$j]}
                            a[$j]=${a[$c]}
                            a[$c]=$t
                    fi
                    done
    done
    echo ${a[*]}
    [root@aming shellDir]# sh 3arry.sh
    28927 7755 29130 16348 8305 4271 25701 16865 22021 30807
    4271 7755 8305 16348 16865 22021 25701 28927 29130 30807

判断符号表示

> -gt
< -lt
== -eq
!=  -ne
>= -ge
<= -le

select用法

select check_phpmod in have noHave
do
  case $check_phpmod in
    have)
    break
    ;;
    noHave)
    echo "install php mod  json  pdo_mysq first "
    exit 1
    ;;
    *)
    echo "only 1(have) or 2(noHave)"
    exit 1
    ;;
  esac
done

 脚本分区

fdisk $dev_name  &>/dev/null <<EOF
d
n
p
1

+512M

w
EOF

脚本所有正确和错误输出指定文件

exec 1>> /tmp/acc.log 2>> /tmp/err.log

date #时间命令

符号的表示:
    date +%F     日期
    date +%T      时间
    date +%Y      4位年
    date +%y        2位年
    date +%m      月
    date +%d        日
    date +%H         时
    date +%M        分
    date +%S       秒
    date +%w       第几周
    date +%W      今年的第几周,一年有52周
显示时间:
    date +"%F %T" #显示结果 2017-02-06 22:16:39
    date +"TIME is %F %H:%M:%S" #TIME is 2017-02-06 22:17:43
    date +"%Y-%m-%d %H:%M:%S" #2016-08-26 01:11:17
    date +%s #显示时间戳
    date -d '2013-2-22 22:14' +%s #指定日期的时间戳

指定时间:
    date -d "-2 days" +%F
    date -d "-2 month" +%F
    date -d "-2 year" +%F
    date -d "-2 hour" +%T
    date -d "-2 minute" +%T
    date -d "-200 second" +%T
    date -d  "+1 days 20150401" +%Y%m%d
    agoDate=`date -d "-1 minutes" +"%Y:%H:%M"`
时间戳转日期:
    date -d @1361542596 #Fri Feb 22 22:16:36 CST 2013
    date -d @12884342 +"%Y-%m-%d %H:%M:%S" #2013-02-22 22:16:36
设定时间:
    date  -s "2015-5-8 19:48:00"
常用:
  date +"%Y-%m-%d_%H-%M-%S"
date -d "-1 day"  +"%Y-%m-%d_%H-%M-%S"

[] 判断用法

-s file     文件大小非0时为真
[ -f "somefile" ] :判断是否是一个文件
[ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
[ -n "$var" ] :判断$var变量是否有值,非空为真
[ -z "$var" ] : 空为真
[ "$a" = "$b" ] :判断$a和$b是否相等
-r file     用户可读为真
-w file     用户可写为真
-x file     用户可执行为真
-f file     文件为正规文件为真
-d file     文件为目录为真
-c file     文件为字符特殊文件为真
-b file     文件为块特殊文件为真
-s file     文件大小非0时为真
-t file     当文件描述符(默认为1)指定的设备为终端时为真

判断两数大小

if ( [ "`echo "$tps >= $crit_tps" | bc`" == "1" ] || [ "`echo "$kbread >= $crit_read" | bc`" == "1" ] || 
[ "`echo "$kbwritten >= $crit_written" | bc`" == "1" ]  )
    then
        msg="CRITICAL"
        status=2
else if ( [ "`echo "$tps >= $warn_tps" | bc`" == "1" ] || [ "`echo "$kbread >= $warn_read" | bc`" == "1" ] || 
[ "`echo "$kbwritten >= $warn_written" | bc`" == "1" ]   )
    then
        msg="WARNING"
        status=1
else
    msg="OK"
    status=0
fi

解析参数

[root@git-ued /opt/sh 12:23:18&&11]#cat test.sh

#!/bin/bash
#sh test.sh -d 5 -w w -c c -s 10

while getopts "d:s:w:c:h" OPT; do
    case $OPT in
        "d") disk=$OPTARG;;
        "w") warning=$OPTARG;;
        "c") critical=$OPTARG;;
        "s") second=$OPTARG;;
        "h") help;;
    esac
done

echo $disk $warning $critical $second

 检查参数不能为空

[ ! -b "/dev/$disk" ] && echo "ERROR: Device incorrectly specified" && help

( [ "$warn_tps" == "" ] || [ "$warn_read" == "" ] || [ "$warn_written" == "" ] || 
  [ "$crit_tps" == "" ] || [ "$crit_read" == "" ] || [ "$crit_written" == "" ] ) &&
    echo "ERROR: You must specify all warning and critical levels" && help

( [ "$second" == "" ] ) && second=1

( [[ "$second" -ge "$maxsecond" ]]) && second=10

( [[ "$warn_tps" -ge  "$crit_tps" ]] || 
  [[ "$warn_read" -ge  "$crit_read" ]] || 
  [[ "$warn_written" -ge  "$crit_written" ]] ) && 
  echo "ERROR: critical levels must be highter than warning levels" && help

特殊字符:*,?,\,>,>>,2>,2>>,;,~,&,[],&&,||

* 表示通配符   ?批配单个  #注释
 脱义符   可以把特殊符号变成普通字符
|  管道符  cat /etc/passwd  |  wc -l
>  >>  重定向和重定向追加   echo "abc"  > 1.txt
2>   2>>  错误重写向   ls abcd 2> 1.txt
< 反重写向  如:wc -l  < 1.txt  这种写法不常见
$   变量前缀     前面命令的最后参数!$    文本中是行尾,尾行
; 连接命令
~ 用户家目录
& 命令后面,把这个命令放在后台运行
&&  并且
||  或者
[0-9]  批配0-9中的任意一个
ls [12].txt  相当于  ls 1.txt  2.txt

逻辑运算&&,||,;,!:

&&     并
    ls 1.tx && ls 2.txt  前面的执行成功,后面命令才会执行   常用左边逻辑真
||     或
    ls 1.txt || ls 2.txt  只执行一个命令,前面的成功,后面不执行。前面的不成功,后面的执行。常用左边逻辑非
;  和
    ls /home/ ; cd /home
!    取反
    [ ! -f /tmp/1.txt ] && touch /tmp/1.txt

函数:

注意
1.  函数中的变量在shell中是会被在外面使用的,要想不被使用   local  number=1
2. function myFun(){}    function是可以不写的
3. 函数位置必须在调用之前
4. 函数返回值只能是数字,用echo $?  来获得这个返回值
例1:
    [root@aming shellDir]# cat 3fun.sh
    #!/bin/bash
    ##
    ##
    function sumFun(){
        sum=$[$1+$2]
        echo $sum
        return $sum
    }
    sumFun 1 3
    returnSum=`echo $?`
    echo "w m d sum: $returnSum"

while

例1:死循环
    #!/bin/bash
    while :
    do
            date +%T
            sleep 3
    done
例2: 判断条件
    #!/bin/bash
    n=1
    while [ $n -le 10 ]
    do
            echo $n
            n=$[$n+1]
    done
例3. 直到输入数字为至。
    #!/bin/bash
    n=1
    number=0
    while [ -n "$n" ]
    do
            read -p "please input a number : " number
            n=`echo $number | sed "s/[0-9]//g"`
    done
    echo "this number is : $number"
例3.批量添加用户
    #!/bin/bash
    ##
    if [ -f /root/user.txt ]
    then
        exec < /root/user.txt
        while read line
        do
            username=`echo $line | awk '{print $1}'`
            password=`echo $line | awk '{print $2}'`
            useradd $username && echo $password | passwd --stdin $username
        done
    else
        echo "user.txt is not have..."
    fi

if

if
例 grep -q "$name" /etc/passwd    -q参数是批配到也不输出,在if判断中批配到就是真
    [root@aming shellDir]# cat 7.sh
    #!/bin/bash
    ##
    ##
    read -t 10 -p "please input a user name:" name
    name="^$name:"
    if  grep -q "$name" /etc/passwd
    then
        echo "is have"
    else
        echo "no have"
    fi
例1.   if  [  ] then  fi
    [root@aming shellDir]# cat 4.sh
    #/bin/bash
    ##   if [ $a -gt $b ]   注意空格
    ##
    a=$1
    b=$2
    echo "$a=$a  $b=$b"
    if [ $a -gt $b ]
    then
             echo "$a > $b"
    fi
    [root@aming shellDir]# sh 4.sh    5  3
    $a=5  $b=3
    5 > 3

例2.   if [ ] then  else fi
    [root@aming shellDir]# cat 4.sh
    #/bin/bash
    ##
    ##
    a=$1
    b=$2
    echo "$a=$a  $b=$b"
    if [ $a -gt $b ]
    then
             echo "$a > $b"
    else
            echo "$a <= $b"
    fi
    [root@aming shellDir]# sh 4.sh  3  4
    $a=3  $b=4
    3 <= 4
例3. if [ ] then elif [ ] then else fi     注意:elif []  then  可以多个
    [root@aming shellDir]# cat 4.sh
    #/bin/bash
    ##
    ##
    read -t 10 -p "please input your score :" number
    if [ $number -gt 90 ]
    then
             echo " is good "
    elif [ $number -gt 70 ]
    then
            echo " is middle"
    elif [ $number -gt 60 ]
    then
            echo " is bad"
    else
            echo "is.........you are die"
    fi
    [root@aming shellDir]# sh 4.sh
    please input your score :95
     is good
    [root@aming shellDir]# sh 4.sh
    please input your score :80
     is middle
    [root@aming shellDir]# sh 4.sh
    please input your score :65
    is bad

for

for
例1. 循环相加
    [root@aming shellDir]# cat 9for.sh
    #!/bin/bash
    ##
    ##
    for i in `seq 1 10`
    do
            echo "$i"
    done
    sum=0
    for i in {1..10}
    do
            sum=$[$i+$sum]
    done
    echo $sum
    [root@aming shellDir]# sh 9for.sh
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    55
例2. for循环中  文件内容 把空格当分隔符    for默认就可以按照空格或者行来遍历
    [root@aming shellDir]# cat 10for.sh
    #!/bin/bash
    ##
    ##
    fileName="1.txt"
    [ -f $fileName ] || cp /etc/passwd ./$fileName

    for i in `cat $fileName`
    do
            echo $i
    done
    [root@aming shellDir]# cat 1.txt
    1 2 3
    1111111111111111
    22222222222
    [root@aming shellDir]# sh 10for.sh
    1
    2
    3
    1111111111111111
    22222222222
例3. 循环ls结果
    [root@aming shellDir]# for file in `ls` ; do echo $file;done
    10for.sh
    1.sh
    1.txt
    2.sh
    3.sh
    4.sh
    5.sh
    6.sh
    7.sh
    8case.sh
    9for.sh

seq

seq
例1:
    [root@aming shellDir]# seq 1 10
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
例2:
    [root@aming shellDir]# seq -w 1 10    注意:-w参数把位数定在 最大位上
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
例3:
    [root@aming shellDir]# seq 1 2 10    中间的2是位长
    1
    3
    5
    7
    9
例3:
    [root@aming shellDir]# seq 10 -2 1
    10
    8
    6
    4
    2

case

例1:
    [root@aming shellDir]# cat 8case.sh
    #!/bin/bash
    ##
    ##
    read -t 10 -p " please input a number: " n
    number=`echo $n | sed "s/[0-9.]//g"`
    if [ -n "$number" ]
    then
            echo "is not a number...."
    else
            n=$[$n%2]
            case $n in
            0)
                    echo "is odd..."
                    ;;
            1)
                    echo "is even..."
                    ;;
            *)
                    ;;
            esac

    fi

可以用${file}分别替换得到不同的值

${file#*/}:删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:删掉最后一个 /  及其左边的字符串:my.file.txt
${file#*.}:删掉第一个 .  及其左边的字符串:file.txt
${file##*.}:删掉最后一个 .  及其左边的字符串:txt
${file%/*}:删掉最后一个  /  及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:删掉第一个 /  及其右边的字符串:(空值)
${file%.*}:删掉最后一个  .  及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:删掉第一个  .   及其右边的字符串:/dir1/dir2/dir3/my

脚本中set -e

set -e #执行过程出错就退出,不会滚血球,越滚越严重

脚本所在目录

cd `dirname $0` #脚本所在目录

脚本中各参数的函数

$0   :代表脚本自身;
$1   :代表脚本传入的第一个参数;
$2   :代表脚本传入的第二个参数;
$#   :代表传递给脚本或函数的参数个数;
$*   :传递给脚本或函数的所有参数。该参数是否包含在 “ ” 内是有区别的;
$@   :传递给脚本或函数的所有参数。该参数是否包含在 “ ” 内是没有区别的;
$?   :上个命令的退出状态,或函数的返回值;
$   : 当前Shell进程ID;

正则通配符号说明

.  表示任意一个字符,包括特殊符号
*  表示*号前面的字符,0个或多个 等价于 {0,}
.*   表示任意个任意字符
?  0或1个?号前面的字符 等价于{0,1}
+  1个或多个+号前面的字符 等价于 {1,}
(abc)  #把abc当位一起的
    egrep '(rr){1,3}' /etc/passwd   ()里的出现1到3次都可以
? + 用egrep,要用grep 必须脱义  或加 -E参数

awk

解释一下:在awk中使用脱义字符是起不到作用的,如果想打印特殊字符,只能使用' " " ' 这样的组合才可以。
这里自左至右为单引号 双引号 双引号 单引号其中两个单引号为一对,
例:
    想脱义$那就是' "$" ' 脱义单引号那就是 ' " ' " '

awk求和:
    df -m | sed -n '2,$'p | awk '{tot=tot+$2} END {print tot/1024}'

awk求平均值:
    tps=`echo "$iostatus" | awk '{(tot=tot+$2)} ; END {print tot/NR}'`
截取文档中的某段 -F 指定分隔符号
    awk -F ':' '{print $1}' 1.txt
使用自定义符连接每一段
    awk -F ':' '{print $1"#"$2"#"$3}' 1.txt
    awk -F ':' '{OFS="#"} {print $1,$2,$3}' 1.txt
匹配
    awk '/oo/' 1.txt
    awk '/root|hui/' /etc/passwd
    awk '/root/&&/hui/' 1.txt
    针对某个段 匹配
        awk -F ':'  '$1 ~/oo/' 1.txt
        awk -F ':' '$1 ~/^h/' 1.txt
    多次区配
        awk -F ':' '/root/ {print $1,$3}; $1 ~/test/; $3 ~/20/' 1.txt
    awk中也可以使用if关键词
        awk -F ':' '{if($1=="root") print $0}' 1.txt

条件操作符  ==,>,<,!=,>=,<=
    第三段为0
        awk -F ':' '$3=="0"' 1.txt
    第三段大于等于500
        awk -F ':' '$3>=500' 1.txt 说明 :当比较数字时,不能加双引号,如果写成$3>="500" 就不符合我们的需求
    第七段不是'/sbin/nologin'
        awk -F ':' '$7!="/sbin/nologin"' 1.txt
    第三段小于第四段
        awk -F ':' '$3<$4' 1.txt
    第三段大于5,并且第三段小于7
        awk -F ':' '$3>5 && $3<7' 1.txt
    第三段大于5或者第七段为'/bin/bash'
        awk -F ':' '$3>5 || $7=="/bin/bash"' 1.txt
awk内置变量NF(段数)  NR(行数)
    head -n3 1.txt | awk -F ':' '{print NF}'
    head -n3 1.txt | awk -F ':' '{print $NF}'
    head -n3 1.txt | awk -F ':' '{print NR}'
    打印20行以后的行
        awk 'NR>20' 1.txt
    打印20行以后并且第一段包含ssh的行
        awk -F ':' 'NR>20 && $1 ~/ssh/' 1.txt
更改某个段的值
    awk -F ':' '$1="root"' 1.txt
数学计算,把第三段和第四段值相加,并赋予第七段
    awk -F ':' '{$7=$3+$4; print $0}' 1.txt
    awk -F ':' '{OFS=":"} {$7=$3+$4; print $0}' 1.txt 显示分隔符
#统计网站日uv
    awk '{print $1}' /data/nginx/logs/access_2015-06-18.log |sort |uniq -c|sort -rn |awk '{print $2}'|uniq -c |awk '{(tot=tot+$1)}; END {print tot}'
#统计某个时间段的日志
    #!/usr/bin/env bash
    set -e
    set -x
    #设置要统计的起始时间
    INTIME='[15/Mar/2017:08:10:01'

    #设置要统计的结束时间
    LASTIME='[15/Mar/2017:09:00:00'

    #定义日志路径:
    LOG='/data/nginx/logs/app/access_2017-03-15.log'

    #统计访问正常的:
    awk "$4 >= "${INTIME}" && $4 <= "${LASTIME}"" $LOG |egrep '200|301|302' |wc -l

    #统计访问有问题的:
    awk "$4 >= "${INTIME}" && $4 <= "${LASTIME}"" $LOG |egrep -v '200|301|302' |wc -l

    #3156
        awk '$4 >= "[30/Jul/2017:19:00:00" && $4 <= "[30/Jul/2017:21:00:00" '  /usr/local/nginx/logs/www.3156.cn.log

sed

替换
    sed替换  可用///  ###   @@@
    sed '1,10s#nologin#login#g' 1.txt  1到10行替换  g是全局
    sed 's#nologin#login#g' 1.txt  全文本替换
    可以脱义路径符/

    sed 's/^.*$/login/g' 1.txt   所有行换成 login
    sed 's/[0-9]//g' 1.txt   数字清空
    sed 's/[a-Z]//g' 1.txt  所有字母清空
    sed 's/[^0-9a-Z]//g' 1.txt  非字母数字清空
    sed -r 's/([a-Z0-9]+)(:.*:)(.*$)/321/g' 1.txt   头尾互换   -r脱义+号  ()把行分为3段
    sed 's/^.*$/& login/g' 1.txt  每行后面加 空格login
    sed 's/^/#/g' 1.txt 行头加#
匹配
    sed -n '10'p 1.txt  打印第10行
    sed -n '1,10'p 1.txt  打印第1到10行
    sed -n '10,$'p 1.txt  打印第10行到末行
    sed -n '/root/'p 1.txt 打印出包含root的行,比grep多//   多p
    sed -n '/r.o/'p 1.txt   =====grep 'r.o' /etc/passwd   ==r.o 表示ro中间任意一个字符都能批配   批配一个
    sed -n '/r*o/'p 1.txt ==========grep 'r*o' /etc/passwd  == 表示0个或多个*前面的字符
    sed -n '/r.*o/'p 1.txt===========grep 'r.*o'  /etc/passwd  == 表示0个或多个任意字符,*前面
    sed -n '/r?o/'p 1.txt ==========grep 'r?o' /etc/passwd  == 表示0个或1个?前面的字符
    sed -n '/r+o/'p 1.txt ========== grep 'r+o' /etc/passwd   一个或多个+号前面的字符
    sed -n '/root|nologin/'p 1.txt  ======== grep --color 'root|nologin' 1.txt  批配root,nologin行
    sed -n '/root/p; /games/p' 1.txt  ===========sed -n -e '/root/'p  -e '/games/'p 1.txt    批配root,games
    sed -n '/(oo)+/'p 1.txt  ============grep -E '(oo)+' 1.txt  批配1对或多对oo
    sed -r -n '/(oo)+/'p 1.txt  =======sed -n '/(oo)+/'p 1.txt    sed  -r  相当对  grep -E 的功能,可以不脱义
删除
    sed '/^$/'d 1.txt  == 相当于grep的 -v 取反   grep --color -v '^$' 1.txt
    sed '1,19'd 1.txt    删除1到19行,不写入文件,只显示在屏幕上
    sed -i '1,5'd 1.txt  删除1到5行,写入文件。  -i参数的作用,  不建议用,怕误操作。
sed最后添加一行
    sed -i '$acommand[check_iostat]=/usr/local/nagios/libexec/check_iostat -d sda -w 100,200,300 -c 200,300,400 -s 10 ' /usr/local/nagios/etc/nrpe.cfg
sed批配行后加一行
    sed -i '/^[mysqld]$/adatadir = /data/mysql' /etc/my.cnf
sed匹配行首加#
    sed '/root/ s/^/#/' /etc/passwd
sed更多用法:
    http://www.361way.com/sed-process-lines/2263.html
sed批配行后面的数据
    sed -n '/2017-11-24 17:10/,$'p catalina.out
脚本中暂停tail -f
    tail -f text.log | sed '/JVM running/Q'

grep和egrep

grep 过滤出指定的行
    #grep  批配ip格式
        grep '([0-9]{1,3}.){3}[0-9]{1,3}'
    grep 'root' /etc/passwd
    grep -i  不区分大小写
    grep --color 'root'  /etc/passwd  把批配的字符标颜色
    grep -o root /etc/passwd 仅显示匹配的字符
    grep -q root /etc/passwd #匹配到内容也不输出,常用在脚本中
    grep -n 'root' /etc/passwd  把批配的行显示出行号
    grep -c 'root'  /etc/passwd  把批配的行数显示出来  ,如果只有2行就显示2
    grep -v 'root'  /etc/passwd  把不批配的行显示出来,也就是取反
    grep -A 2 'root'  /etc/passwd  把批配行和下面2行都显示出来
    grep -B 2 'root'  /etc/passwd  把批配行和上面2行都显示出来
    grep -C 2 'root'  /etc/passwd  把批配行和上面2行,下面2行都显示出来
    grep -r 'iptables'  /etc/*  遍历批配
    grep -r --include="*.php" 'eval' /data/  把一个目录下,过滤所有*.php文档中含有eval的行
    grep '[0-9]' /etc/passwd   过滤出包含数字的行
    grep '[aN]'  /etc/passwd  过滤出包含a,N的行
    grep '[a-zA-Z]' /etc/passwd  过滤出包含字母的行
    grep '^[a-z]' /etc/passwd  过滤出以小写字母开头的行
    grep '[0-9]' /etc/passwd  含数字的行
    grep '[^0-9]'  /etc/passwd  含有非数字的行
    grep -v '[^0-9]' 1.txt 不含有非数字的行   纯数字
    grep '^&' 1.txt  空行
    grep 'r.o' /etc/passwd   ==r.o 表示ro中间任意一个字符都能批配   批配一个
    grep 'r*o' /etc/passwd  == 表示0个或多个*前面的字符
    grep 'r.*o'  /etc/passwd  == 表示0个或多个任意字符,*前面
    grep 'r?o' /etc/passwd  == 表示0个或1个?前面的字符
    grep -E 'r?o' /etc/passwd  === grep 'r?o' /etc/passwd   结果是一样的
    grep -E == egrep   egrep能用的  grep -E 都能用
    egrep 'r+o' /etc/passwd   一个或多个+号前面的字符   ===grep -E 'r+o' /etc/passwd
egrep
    egrep 'root|aming' /etc/passwd    |表示或的意思
    grep 'root' /etc/passwd | grep 'aming' /etc/passwd   批配root又批配aming  用这种 方式表示并且
    egrep '(rr)+' /etc/passwd  表示 批配1个或多个()里的字符
    egrep '(rr){1,3}' /etc/passwd   ()里的出现1到3次都可以

脚本中退出tail -f

tail -f text.log | sed '/JVM running/Q'

shell解析json

下载jq 二进制文件
https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64

cp jq-linux64 /usr/bin
cd /usr/bin
mv jq-linux64 jq
chmod +x jq

#json文件如下,ceshi.json
{
    "menu": {
        "id": "file",
        "value": "File:",
        "popup": {
            "menuitem": {
                "value": "New",
                "onclick": "CreateNewDoc()"
            }
        }
    }
}


##解析
cat ceshi.json | jq .menu.id | sed 's/"//g'
原文地址:https://www.cnblogs.com/hanxiaohui/p/8805699.html