shell

Posted 北极菜鸟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell相关的知识,希望对你有一定的参考价值。

 

1、shell简介

       shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕返回给用户。这种对话方式可以是交互的方式(从键盘输入命令,可以立即得到shell的回应),或非交互(脚本)的方式。换句话说,Shell是一个命令行解释器,它为用户提供一个像Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动,挂起,停止甚至是编写一些程序。

      Shell还是一个功能相当请打的编程语言,易编写,易调试,灵活性较强。Shell是解释执行的脚本语言,在Shell中可以直接调用Linux系统命令。

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

2、shell变量

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

2.1 什么是变量:变量就是用一个固定的字符串(也可能是字符、数字等组合)代替更多更复杂的内容,该内容可能还会包含变量、路径、字符串等其他路径。

                                   

2.2 变量分类:环境变量(全局变量)和普通变量(局部变量)

2.2.1 普通变量

      定义变量和打印变量示例:

       删除变量:unset  变量名 

2.2.2自定义环境变量

        设置环境变量                   !!!环境变量名通常要大写

        <== 查看环境变量set、env、declare

         删除环境变量:unset  变量名

    (1)用户环境 变量配置文件:/root/.bashrc

    (2)全局变量配置文件:/etc/profile

                        /etc/bashrc                      #<==推荐此文件优先设置

                   /etc/profile.d/

2.2.3设置登录提示

 <==在/etc/motd   文件中加入提示语即可

2.2.4变量定义及变量输出说明

       单引号:所见即所得。

  双引号:弱引用,输出所有内容,如果内容中有命令(要反引下)、变量、特殊字符要转义。

       反引号:引用命令。

注意:这里仅为Linux  shell下的结论

示例:

[root@localhost ~]# echo \'today is date\'          <==单引号,所见即所。

today is date
[root@localhost ~]# echo \'today is `date`\'        <==单引号引起内容时,内部有命令通过反引号引起来也没用。
today is `date`
[root@localhost ~]# echo "today is `date`"        <==用双引号,内部有命令通过反引号引起来有用。
today is Fri Oct 27 17:49:44 CST 2017
[root@localhost ~]# echo "today is date"           <==双引号,输出说有。
today is date
[root@localhost ~]# echo today is $(date)          <==$()相当于 ` ` 。

today is Fri Oct 27 17:50:37 CST 2017。

2.2.5针对AWK调用shell变量,使用引号情况介绍

1、赋值不加引号

[root@localhost ~]# a=123                   <==定义变量a,并赋值123,没加引号。

[root@localhost ~]# awk \'BEGIN {print "$a"}\'         <==加双引号引用$a,输出本身。
$a
[root@localhost ~]# awk \'BEGIN {print $a}\'          <==不加引号引用$a,输出空。

[root@localhost ~]# awk \'BEGIN {print "\'$a\'"}\'       <==给$a加单引号,再加双引号,输出结果。
123

2、赋值加单引号

[root@localhost ~]# a=\'666\'                      <==定义变量a,并赋值666,加单引号。

[root@localhost ~]# awk \'BEGIN {print "$a"}\'
$a
[root@localhost ~]# awk \'BEGIN {print $a}\'

[root@localhost ~]# awk \'BEGIN {print "\'$a\'"}\'
666
[root@localhost ~]# awk \'BEGIN {print \'$a\'}\'          <==加单引号,输出结果。
666

3、赋值加双引号

[root@localhost ~]# a="666"                        <==定义变量a,赋值666,加双引号。

[root@localhost ~]# awk \'BEGIN {print "$a"}\'
$a
[root@localhost ~]# awk \'BEGIN {print $a}\'

[root@localhost ~]# awk \'BEGIN {print \'$a\'}\'          <==给$a加单引号,再加双引号,输出结果。
666
[root@localhost ~]# awk \'BEGIN {print "\'$a\'"}\'

666

4、赋值加反引号

[root@localhost ~]# a=`pwd`
[root@localhost ~]# echo $a
/root
[root@localhost ~]# awk \'BEGIN {print $a}\'

[root@localhost ~]# awk \'BEGIN {print "$a"}\'
$a
[root@localhost ~]# awk \'BEGIN {print \'$a\'}\'
awk: cmd. line:1: BEGIN {print /root}
awk: cmd. line:1: ^ unterminated regexp
awk: cmd. line:1: BEGIN {print /root}
awk: cmd. line:1: ^ unexpected newline or end of string
[root@localhost ~]# awk \'BEGIN {print "\'$a\'"}\'
/root

结论:不管变量如何定义赋值,在AWK取用shell变量时,我们更喜欢先用echo加符号输出变量,然后通过管道给awk,进而控制变量的输出结果。举例如下:

 

[root@localhost ~]# a="rookie"
[root@localhost ~]# echo $a | awk \'{print $1}\'
rookie
[root@localhost ~]# echo $a | awk \'{print $0}\'
rookie

 

2.2.6变量定义总结

(1)变量名为只能为字母、数字、下划线,只能以字母或下划线开头。

(2)变量名定义要规范,并且见名知意。

(3)一般变量定义、赋值用双引号,简单连续字符可以不加引号。

(4)希望解析变量结果用反引号或$().

2.3  shell中特殊且重要的变量

2.3.1位置参数变量

  $0     获取当前执行shell脚本的文件名。

  $n     获取当前执行的shell脚本的第几个参数,n=1....9,n>9时,用花括号括起来例:${10}

  $#     获取当前执行shell脚本后面接的参数的总个数。

  $*      获取当前shell脚本所有传参的参数,不加引号和$@相同。

  $@    获取当前shell脚本参数所有传参的参数,不加引号和$*相同。例如:"$@" 相当于"$1" "$2"...           表示独立字符串。当"$@"和"$*"都加引号时,两者有区别,都不加,两者无区别。

2.3.2 shell进程中特殊状态变量

  $?     获取执行上条指令的执行结果返回值(0为成功,非0失败),用于判断上条命令执行是否成功。常用命令

  $$     获取当前执行的shell脚本的进程号(PID)。不常用

  $!       获取上一个后台工作进程的进程号(PID)。不常用

  $_      获取在此之前执行的命令或脚本最后一个参数。不常用

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

3、变量数值运算

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

3.1算数运算符

  

  

双小括号的使用方法

  

let 命令用法:

[root@localhost ~]# i=2
[root@localhost ~]# let i=i+8
[root@localhost ~]# echo $i
10

提示:let i=i+8等同于((i=i+8)),但后者效率更高。

expr命令用法:

[root@localhost ~]# expr 2+2        <==注意数字与符号间要有空格
2+2
[root@localhost ~]# expr 2 + 2
4
[root@localhost ~]# expr 2 - 2
0
[root@localhost ~]# expr 2 * 2             <==*要用 \\ 转义
expr: syntax error
[root@localhost ~]# expr 2 \\* 2
4
[root@localhost ~]# expr 2 / 2
1

 bc命令用法:

[root@localhost ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty\'.
1+2                                          <== 输入后按回车
3
2*3
6

 例1:此方法效率低,不推荐使用

[root@localhost ~]# i=5
[root@localhost ~]# i=`echo $i+6 | bc`
[root@localhost ~]# echo $i
11

 AWK实现计算

[root@localhost ~]# echo "3.4 2.9" | awk \'{print ($1-$2)}\'
0.5
[root@localhost ~]# echo "3 9" | awk \'{print ($1+6)}\'
9
[root@localhost ~]# echo "334 21" | awk \'{print ($1-300)/$2}\'
1.61905
[root@localhost ~]# echo "334 21" | awk \'{print ($1-300)*$2}\'
714

declare(同typeset)命令用法

[root@localhost ~]# declare -i A=20 B=19    <== -i参数可以将变量定义为整形
[root@localhost ~]# A=A+B
[root@localhost ~]# echo $A
39

$[]符号运算

[root@localhost ~]# echo $i
10
[root@localhost ~]# echo $[2*3]
6
[root@localhost ~]# echo $[2**3]
8
[root@localhost ~]# echo $[2/3]
0
[root@localhost ~]# echo $[3/2]
1
[root@localhost ~]# echo $[3%2]
1
[root@localhost ~]# echo $[1%2]
1
[root@localhost ~]# echo $[3%5]
3

read命令 

语法格式:read [参数] [变量名]

常用参数: -p prompt  设置提示信息。

                -t  timeout  设置输入等待时间,默认单位秒。

例:

[root@localhost ~]# read -p "please input one num:" num
please input one num:666
[root@localhost ~]# echo $num
666

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

4 、shell脚本条件测试与比较

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

4.1条件测试

  

注意事项:1、语法一中test命令和语法2中的[] 等价。语法3中[[]]为扩展test命令。语法4中()())常用于计算。

                   2、[[]]中可以使用通配符等进行模式匹配,这是其区别于其他语法。

                   3、&&、||、>、< 等操作符可以应用在[[]]中。

                         -a、-o、-gt、-lt、-eq、-ne、-ge、-le  代替以上操作符。

                   4、对于整数的关系运算,也可以用shell的算数运算符(())。

test<测试表达式>示例:

[root@localhost ~]# test -f file && echo true || echo false
true

[<测试表达式>] 示例:

[root@localhost ~]# [ -f /test/file1 ] && echo 1 || echo 0
0

[[<测试表达式>]] 示例:

[root@localhost ~]# [[ -f /test/file1 ]] && echo 1 || echo 0
0

4.2 文件测试

  

 这些操作符对于[[]] 、[] 、test的测试都是通用。

4.3 特殊条件测试

4.4 字符串测试表达式

4.4.1 字符串测试操作符

  

提示:1对于字符串测试,一定要将字符串加引号之后在比较。如[ -n "ahjhfhe" ].

           2、比价符号两端一定要有空格。

            3、“!=”和‘=’可用于比较两个字符串是否相同。

 

 4.5 整数二元比较操作符

  

4.6 逻辑操作符

  

4.7  测试表达总结

  

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

5、if条件语句

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

5.1、单分支结构
语法:
if 条件
     then
        命令序列
fi

if 条件;then
    命令序列
fi

复合命令:条件满足时,执行若干个命令
使用{}或者()
书写规则:
(list) 在子shell中执行命令列表
{ list} 在当前shell中执行命令列表,指令写在一行{必须有空客,最后一个指令以;结束。
示例1:两个整数比较大小
示例2:测试脚本执行者,若不是root用户,给出提示后则退出。
退出 exit 1
思路:
1、使用系统环境变量做判断 USER UID
2、使用命令结果做判断
whoami、id -u
示例3:判断系统内存剩余大小,低于200M邮件报警。

5.2、双分支结构
语法:
if 条件
then
  命令1
else
命令2
fi
示例4:双分支if条件语句整数比较大小
示例5:判断脚本目录是否存在,存在打印目录存在信息,否则创建目录。
示例6:判断目标主机是否存活,显示检测结果
ping -c 3 -i 0.2 -W 3 192.168.1.111 &> /dev/null

检测web服务器是否正常访问,正常显示检测结果,异常重启apache。


5.3.多分支结构
语法:

if 条件1
  then
   命令1
elif 条件2
  then
    命令2
else
  命令n
fi

判断当前主机的CPU生产商,其信息在/proc/cpuinfo文件中vendor_id一行中。
如果其生产商为GenuineIntel,就显示其为Intel公司;
如果其生产商为AuthenticAMD,就显示其为AMD公司;
否则,就显示无法识别;
vendor=`grep vendor_id /proc/cpuinfo |uniq |cut -d\' \' -f2`


判断分数范围,分出优秀、良好、合格、不合格四档
85-100 优秀--A [ $score -ge 85 -a $score -le 100 ]
70-84 良好--B [ $score -ge 70 -a $score -lt 85 ]
60-69 合格--C [ $score -ge 60 -a $score -lt 70 ]
60分以下不合格--D else

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

6、case多分支
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
case “var” in
pattern1) list1;;
pattern2) list2;;
...
            *) listn;;
esac

示例1:根据用户输入,判断出该字符是字母、数字或者其他字符
read -p "please input a character: " num
case "$num" in
[a-zA-Z])
          echo "$num is letter"
;;
[0-9])
          echo "Snum is digit"
;;
*)
           echo "Other!"
esac

示例2:将判断分数范围多分支语句用case语句实现

case语句编写服务启动脚本

系统示例脚本:

/etc/init.d/portmap


----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7、循环
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7.1、while
当型循环

while condition
do
      list
done

循环语句:
1、变量初始值
2、变量增加
3、避免死循环

示例1:批量创建用户
要求:
用户名以test开头,按数字序号变化;
一共添加30个账号,即test01,test02…,test30
用户初始密码为123456

思路:
i=1
while [ $i -le 30 ]
do
      if [ $i -lt 10 ]
      then
           username=test0$i
      else
            username=test$i
      fi
useradd $username
echo "123456" | passwd --stdin $i
let i++
done
示例2:猜商品价格
         通过变量RANDOM获得随机数
         提示用户猜测并记录次数,猜中后退出循环

          price=`$[$RANDOM%1000]`
          times=0

#/bin/bash

# define var
PRICE=$[$RANDOM % 100]
TIMES=0

while true
do
              read -p "Please enter the product price [0-99] : " INT
              let TIMES++
              if [ $INT -eq $PRICE ]
              then
                        echo "Good luck,you guessed it."
                        echo "You have guessed $TIMES times."
                         exit 0
                elif [ $INT -gt $PRICE ]
                then
                          echo "$INT is too high"
                 else
                           echo "$INT is too low"
                     fi
done

 

while true
do
       list
done

示例3:while读取文件
工作过程中遇到要从一个ip列表中获取ip port,然后ssh ip 到目标机器进行特定的操作

 


while读取文件方法:
方法1:文件描述法
exec < FILE
Sum=0
while read line
do
       cmd
done
方法2:重定向法
cat $FILE | while read line
do
       cmd
done
方法3:read釜底抽薪
while read line
do
         cmd
done < FILE

while read line
do
    IP=`echo $line | cut -d\' \'-f1`
    PORT=`echo $line | cut -d\' \' -f2`
     echo "IP: $IP, PORT: $PORT"
done <ip.txt
另外逐行读取文件效率最高为for循环
for line in $(cat $FILE)
do
      cmd
done

以上方法中for循环效率最高,read 釜底抽薪次之。

 

7.2、until


until condition
do
       list
done

7.3、for

1)列表for循环
语法:
for var in list
     do
          commands
     done
2)不带列表for循环
语法:
for var
     do
          statements
     done
提示:不带列表的,相当于in “$@”。


3)C风格for循环
语法:
for ((exp1;exp2;exp3))
     do
          statements
     done

示例1:直接列出变量列表所有元素

示例2:获取当前目录下的文件名作为变量列表打印输出

示例3:将之前用while语句创建的test01-test30用户删除

示例4:mysql分库分表备份

示例5:不带列表for循环



循环控制结构:
break
循环结构 for/while 中使用,中止循环,若 break 后面指定一个数值 n 的话,则"从里向外"打断第 n 个循环,默认值为 break 1 ,也就是打断当前的循环。

continue
在循环结构 for/while 中使用,提前结束本轮循环,continue 后面也可指定一个数值 n ,以决定继续哪一层(从里向外计算)的循环,默认值为 continue 1 ,也就是继续当前的循环

exit
exit命令用于退出当前shell,在shell脚本中可以终止当前脚本执行

退出码(exit status,或exit code)的约定:
         0表示成功(Zero - Success)
         非0表示失败(Non-Zero - Failure)
           2表示用法不当(Incorrect Usage)
    127表示命令没有找到(Command Not Found)
      126表示不是可执行的(Not an executable)
            >=128 信号产生


7.4、select
select语句结构:

select 变量 in 选项1 选项2
do
         break
done

select 表达式是一种bash的扩展应用,动作包括:
自动用1,2,3,4列出菜单 (没有echo指令,自动显示菜单)
自动read输入选择 (没有 read指令,自动输入)
赋值给变量 (没有赋值指令,自动输入数字后,赋值字符串给变量)

select本身就是一个循环,break是当选择后,就跳出循环

示例:
# vim 01.sh

#/bin/bash

echo "What is your favourite OS?"
select var in Linux Windows Mac other
do
       break
done


echo "You have selected $var"

# sh 01.sh
What is your favourite OS?
1) Linux
2) Windows
3) Mac
4) other
#? 2
You have selected Windows

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

8、函数

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
函数的作用就是把程序里多次调用的相同的代码,定义为一份,然后起个名字,所有的调用都只用这个名字即可。修改代码时,只需要改变函数体内的代码即可。
优势
1、 把相同的程序段定义为函数,可以减少程序代码量;
2、 增加程序可读,易读性;
3、 实现程序的功能模块化;

定义:

格式一:
function 函数名( )
{
       指令…
}

格式二:
函数名()
{
       指令…
}

格式三:
function 函数名
{
       指令…
}


函数结束状态
             执行函数时,函数中最后一个命令的传回值代表函数的结束状态。也可以使用return自定义执行状态返回值,遇到return命令就立即结束,回到调用函数下一个命令,此时函数传回值0。

函数执行:

调用函数:
            直接执行函数名即可。
                    函数名
            带参数的函数执行方法:
                      函数名 参数

示例1:
写一个脚本,判定192.168.0.200-192.168.0.254之间的主机哪些在线。
要求:
1、使用函数来实现一台主机的判定过程;
2、在主程序中来调用此函数判定指定范围内的所有主机的在线情况。
#直接使用函数实现(无参数,无返回值)
#使用函数传参(有参数,无返回值)
#使用函数返回值判断(有参数,有返回值)

示例2:写一个脚本:使用函数完成
1、函数能够接受一个参数,参数为用户名;
判断一个用户是否存在
如果存在,就返回此用户的shell和UID;并返回正常状态值;
如果不存在,就说此用户不存在;并返回错误状态值;
2、在主程序中调用函数;


shell函数与变量作用范围
变量作用范围
没有特别定义均为全局,局部变量使用local定义

移动位置参数shift n

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
9、数组
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

数组(也称Shell数组变量) ---一组数据的集合
普通数组:只能使用整数作为数组下标(数组索引)
关联数组:可以使用字符串作为数组下标(数组索引)



1、定义数组
数组名=(值1 值2 ... 值n)

示例:
array_name=(value0 value1 value2 value3)
或者
array_name=(
value0
value1
value2
value3
)

还可以单独定义数组的各个部分
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
可以不使用连续的下标,而且下标的范围没有限制。

2、数组操作

1)获取数组长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}

2)引用数组
${数组名[下标]}

3)遍历数组
示例:
[root@localhost Scripts]# filename=(`ls`)
[root@localhost Scripts]# for var in ${filename[@]};do echo $var;done
或者
[root@localhost Scripts]# for var in ${filename[*]};do echo $var;done
或者
[root@localhost Scripts]# for ((i=0;i<${#filename[@]};i++));do echo ${filename[i]};done
4)数组的删除
unset array[1] # 删除数组中第一个元素
unset array # 删除整个数组

示例:
1、从“标准输入”读入n次字符串,每次输入的字符串保存在数组array里
i=0
n=5
while [ "$i" -lt $n ] ; do
  echo "Please input strings ... `expr $i + 1`"
  read array[$i]
  b=${array[$i]}
  echo "$b"
  i=`expr $i + 1`
done

2、将字符串里的字母逐个放入数组,并输出到“标准输出”
chars=\'abcdefghijklmnopqrstuvwxyz\'
for (( i=0; i<${#chars}; i++ )) ; do
  array[$i]=${chars:$i:1}
  echo ${array[$i]}
done

${chars:$i:1},表示从chars字符串的 $i 位置开始,获取 1 个字符

3、把1-3 3个数字存到数组里 分别乘以8 然后依次输出。
#!/bin/bash

array1=(`seq 3`)

for ((i=0;i<${#array1[@]};i++))
do
          echo $[${array1[$i]}*8]
done
------------------------------------------------------------------------------
10、正则表达式
------------------------------------------------------------------------------
1、什么是正则表达式?
简单的说,正则表达式就是一套处理大量的字符串而定义的规则和方法。
例如:假设 @代表12345
通过正则表达式这些特殊符号,我们可以快速过滤、替换需要的内容。

2、为什么要学习正则表达式?
在工作中,我们做linux运维工作,时刻面对着大量的日志,程序,命令的输出。
迫切的需要过滤我们需要的一部分内容,甚至是一个字符串。

3、两个注意事项:
1)正则表达式的应用非常广泛,存在于各种语言中,比如PERL,php,JAVA等
我们主要学习linux的正则表达式,系统运维工作中常用的正则表达式
常用的正则表达式命令为grep(egerp),sed,awk。
linux三剑客,要想三剑客玩得更好,那就一定离不开正则表达式。

2)linux正则表达式和我们命令行中其他的命令使用的通配符是有本质区别的。

注意事项:
a、linux正则表达式一般是以行为单位处理。
b、alias grep=\'grep --color=auto\',匹配到高亮显示
c、注意字符集,LC_ALL=C
4、linux正则表达式

10.1 、基于grep来讲。
基础正则表达式:BRE(basic regular expression)
1)^word 表示搜索以word开头的内容。
2)word$ 表示搜索以word结尾的内容。
3)^$ 表示空行,不是空格。
4). 代表且只能代表一个任意字符。
5)\\ 转义字符,让有着特殊身份意义的字符。
例如:\\.只表示小数点,还原原始的小数点的意义。
6)* 重复0个或多个前面的字符
7).* 匹配所有的字符。^.* 任意多个字符开头。
8)[] 匹配字符集合内任意一个字符,如[a-z]
9)[^abc] ^在中括号里表示非,不包含a或b或c
10){n,m} 匹配n到m次,前一个字符。
{n,} 至少N次,多了不限。
{n} N次
{,m} 至多m次,少了不限。
注意:grep要{转义},\\{\\},egrep不需要转义
11)\\<或\\b:锚定词首(支持vi和grep),其后面的任意字符必须作为单词首部出现,如 \\<love或\\blove
12)\\>或\\b:锚定词尾(支持vi和grep),其前面的任意字符必须作为单词尾部出现,如 love\\>或love\\b

后项引用:后面例子中会用到。
分组:
\\(\\)
  \\(ab\\)*
  后项引用
  \\1:引用第一个左括号以及与之对应的右括号所包括的所有内容
  \\2:
  \\3:


扩展正则表达式:
+    重复一个或者一个以上的前一个字符,如o+表示一个以上的o,。+ 等价于 {1,}。
?   0个或者1个前一个字符,如o?表示空白或者1个o,? 等价于 {0,1}。
|    或,如要查找gd或者good这两个字符,egrep -n \'gd|good\' grep.man,可以更多个字符串相或
()    找 组 字符串,如查找glad或者good, egrep -n \'g(la|oo)d\' grep.man
()+    多个重复组的判别,如查找A开头C结尾,中间有一个以上的xyz,egrep -n \'A(xyz)+C\' grep.man

grep命令:
-v:排除匹配的内容
-E:支持扩展的正则表达式
-i:忽略大小写
-o:只输出匹配的内容
--color=auto 匹配的内容显示颜色
-n 在行首显示行号


示例:
1、显示/proc/meminfo文件中以不区分大小的s开头的行;
grep -i \'^s\' /proc/meminfo
或 grep \'^[sS]\' /proc/meminfo
2、显示/etc/passwd中以nologin结尾的行;
grep \'nologin$\' /etc/passwd
3、取出默认shell为/sbin/nologin的用户列表
grep \'/sbin/nologin$\' /etc/passwd | cut -d: -f1
4、取出默认shell为bash,且其用户ID号最小的用户的用户名
grep \'bash$\' /etc/passwd | sort -n -t: -k3 | head -1 | cut -d: -f1
5、显示/etc/inittab中以#开头,且后面跟一个或多个空白字符,而后又跟了任意非空白字符的行;
grep \'^#[[:space:]]\\{1,\\}[^[:space:]]\' /etc/inittab
6、显示/etc/inittab中包含了:一个数字:(即两个冒号中间一个数字)的行;
grep \':[0-9]:\' /etc/inittab
或 grep -o \':[[:digit:]]:\' /etc/inittab
7、显示/boot/grub/grub.conf文件中以一个或多个空白字符开头的行;
grep \'^[:space:]\\{1,\\}\' /boot/grub/grub.conf
8、显示/etc/inittab文件中以一个数字开头并以一个与开头数字相同的数字结尾的行;
grep \'^\\([0-9]\\).*\\1$\' /etc/inittab
或 grep \'^\\([[:digit:]]\\).*\\1$\' /etc/inittab
9、找出/proc/cpuinfo中的,1位数,或2位数;
grep \'[0-9]\\{1,2\\}\' /proc/cpuinfo
或 grep \'[[:digit:]]\\{1,2\\}\' /proc/cpuinfo


10、取出本机所有IP地址(不包括lo),并用如下格式打印
eno16777736: 192.168.95.120
eno33554984: 192.168.253.153
eno50332208: 10.20.0.128

方法一:
#!/bin/bash


Net_Name=(`ifconfig | grep -v "lo:" | egrep "^[[:alpha:]]{1,}" | cut -d\' \' -f1`)
#Net_Name=(`ifconfig | awk \'$1 !~ /lo/ && /^[[:alpha:]]{1,}/ {print $1}\'`)


for var in ${Net_Name[@]}
do
echo -e "$var\\t`ifconfig | grep -A 1 "$var" | grep "inet" |tr -s \' \'|cut -d\' \' -f3`"
#echo -e "$var\\t`ifconfig | grep -A 1 "$var" | awk \'/inet/ {print $2}\'
done

方法二:
#!/bin/bash


Net_Name=(`ip a | egrep "^[0-9]{1,}" | grep -v "lo:"| cut -d\' \' -f2`)
#Net_Name=(`ip a | awk \'$2 !~ /lo/ && /^[0-9]{1,}/ {print $2}\'`)


for var in ${Net_Name[@]}
do
  echo -e "$var\\t`ip a | grep -A 2 "$var" | grep "inet" | tr -s \' \' | cut -d\' \' -f3 | cut -d/ -f1`"
  #echo -e "$var\\t`ip a | grep -A 2 "$var" | awk \'/inet/ {print $2}\' | awk -F/ \'{print $1}\'\'
done

方法三:

Net_Name=(`ifconfig | awk -F: \'$1 !~ /lo/ && /^[[:alpha:]]+/ {print $1}\'`)

for var in ${Net_Name[@]}
do
  echo -e "$var:\\t`ifconfig $var | awk \'NR==2 {print $2}\'`"
done

 

以上是关于shell的主要内容,如果未能解决你的问题,请参考以下文章

Shellshell脚本练习

Shellshell 的执行流控制

shellshell-grep -v 排除多个输出结果

Shellshell中的常用基础命令

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

Shellshell脚本中的变量