linux sed 变成数组,shell中的数组、正则表达式、sed、awk的使用

咱有什么说什么,说实在的,这部分我感觉是liunx中最乱的地方,也是最不好学的,也是能看出人最专业的地方,明白我的意思了吧,,,,自己体会。c892a66900c4250c429cbcc5c082d55d.png

数组 declare

定义变量的类型

declare 选项 变量名=值

选项有

-i ×××的变量

-r 只读的变量 定义就不可以修改了

-x 系统环境变量

-a 数组变量 想把多个变量定义成一个组

---------

[root@xu ~]# declare -i a=1 b=2

[root@xu ~]# declare -i c=$a*$b

[root@xu ~]# echo $c

2

---------

创建数组

[root@xu ~]# declare -a teaname

----------

查看数组

[root@xu ~]# declare -a

------

数组赋值 (添加信息)

数组名 [元素下标]=值

----------

给数组添加内容

[root@xu ~]# teaname[0]=yzs

[root@xu ~]# teaname[1]=xly

[root@xu ~]# teaname[2]=lili

[root@xu ~]# declare -a

declare -a BASH_ARGC='()'

declare -a BASH_ARGV='()'

declare -a BASH_LINENO='()'

declare -a BASH_SOURCE='()'

declare -ar BASH_VERSINFO='([0]="3" [1]="2" [2]="25" [3]="1" [4]="release" [5]="i386-redhat-linux-gnu")'

declare -a DIRSTACK='()'

declare -a FUNCNAME='()'

declare -a GROUPS='()'

declare -a PIPESTATUS='([0]="0")'

declare -a teaname='([0]="yzs" [1]="xly" [2]="lili")'

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

[root@xu ~]# serip=(1.1.1.1 2.2.2.2 3.3.3.3)

[root@xu ~]# declare -a |grep serip

declare -a serip='([0]="1.1.1.1" [1]="2.2.2.2" [2]="3.3.3.3")'

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

输出数组元素

[root@xu ~]# echo ${serip[1]}

2.2.2.2

输出全部元素

[root@xu ~]# echo ${serip[@]}

1.1.1.1 2.2.2.2 3.3.3.3

[root@xu ~]# echo ${serip[*]}

1.1.1.1 2.2.2.2 3.3.3.3

----------

统计数组元素的个数

[root@xu ~]# echo ${#serip[*]}

3

--------

统计模个元素值的长度 (第一个代表0 第二个代表1 1.1.1.1 是7位.也算)

[root@xu ~]# echo ${#serip[0]}

7

---------

输出模个位置的元素 从所有的数组里选取第2个元素

[root@xu ~]# echo ${serip[@]:2}

3.3.3.3

------

[root@xu ~]# hostname=(www.baidu.com www.sina.com www.uplooking.com)

[root@xu ~]# echo ${hostname[2]}

www.uplooking.com

[root@xu ~]# echo ${hostname[2]:0}

www.uplooking.com

[root@xu ~]# echo ${hostname[2]:4}

uplooking.com

[root@xu ~]# echo ${hostname[2]:4:9} 从第几个开始输出 输出几位

uplooking

--------

把从屏幕输入的三次IP 地址 存放到数组serip里

把数组色日跑得三个元素值输出到屏幕上

1 #!/bin/bash

2 read -p "请输入第一个IP地址" a[0]

3 read -p "请输入第二个IP地址" a[1]

4 read -p "请输入第三个IP地址" a[2]

5

6 echo ${a[@]}

用循环的方式给数组赋值

1 #!/bin/bash

2 read -p "清输入监控主机的台数:" a

3 i=0

4 while [ $i -lt $a ]

5 do

6 read -p "清输入第一台主机ip:" serip[$i]

7 let i++

8 done

9

10

11 echo ${serip[@]}

用循环的方式输出数组元素

1 #!/bin/bash

2 read -p "清输入监控主机的台数:" a

3 i=0

4 while [ $i -lt $a ]

5 do

6 read -p "清输入第一台主机ip:" serip[$i]

7 let i++

8 done

9 echo "-------------------------------------------"

10 for i in `echo ${serip[@]}`

11 do

12 echo $i

13 done

14 echo "----------------------------------------"

15 for ((i=0;i

16 do

17 echo ${serip[$i]}

18 done

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

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

正则表达式

正则 是用符号来描述有相同属性的数据

\转意 在普通情况下 是把特殊符号变成普通符号

在grep (正则表达式中) 是把普通符号变成特殊符号 直接写是没有特殊意义的

grep [选项]‘正则表达式’ 文件名

命令| grep [选项]‘正则表达式’ 文件名

处理方式

逐行处理 把与正则表达式匹配的行输出 以行为处理单位

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

正则符号

^ 开头

$ 结尾

^a 以a为开头

^ 以 为开头的

^# 以#开头的

$ 结尾

^$ 有开头和结尾

a$ 以a为结尾的

^ab$ 以a开头 b为结尾的

. 匹配任意单个字符(任意一位)

\.$ 配置以点结尾的行

* 前面的字符出现0此或者无穷次

* >=o o个到多个

+ >= 1 1 个到多个

\? 是0次或1

***************************************************

用grep 的时候 下面的这几个必须要转意

^ $ . [] * \? \+ \{ \} \< >/ \| \( \)

****************************************************

() 保存 匹配的模式

(ab) 一个整体

^pac*j$ c出现0此或者无穷次

^p(ac)*j$ *前面的ac出现0此或者无穷次

[ ] 匹配范围内的也就是任意一个

[afb] 包括 afb里任意一个都匹配

[a-d]只要里面的有任意一个都匹配

[a-Z]所有的字母

.* 表示所有字符

[^a-c] ^在[]表示取反 没有a到c的都匹配

^[a-c] 以abc开头的

^[^a-c] 不以abc开头的行

| 或

(abc|def)* abc出现o到无穷此 或者 def出现0次或者无穷

w(abc|def)x 表示wabcx 或者是wbefx 都匹配

匹配次数

\{ \}指定前面的表达式出现的次数

g\(oo\)\{1\}d =good

g\(oo\)\{2\}d =gooood 俩个oo 出现2次

{2,} >=2

{2,4} >=2 and <=4 最小出现2次最大出现4次

\< \

>/ a>/ 匹配行里以a为结尾的

正则选项

-v 取反

-i 不分大小写

-n 显示匹配文件的行号

-c 显示正则表达式匹配的行数

-q 不显示输出的信息

去掉前面有空格 和#的 只要有效行

[root@xu opt]# grep -v "^$\|^#" /etc/httpd/conf/httpd.conf

面试的时候肯能出现的匹配

匹配出make地址HWADDR

[root@xu opt]# grep "\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}" /etc/sysconfig/network-scripts/ifcfg-eth0

HWADDR=54:E6:FC:71:17:45

ip地址

域名 www . baidu . com

[root@xu opt]# grep "[a-z0-9]\{1,\}\.[a-z0-9]\{1,\}\.[a-z]\{2,3\}" ifcfg-eth0 aaawww.baidu.com

主机名

url 地址 论坛上贴网址的

邮箱

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

sed 交换式的流编辑器

打印 删除 替换 复制 剪切 粘贴 导入 导出

处理的时候以行为单位 对文件进行逐行处理

用法

sed [ 选项] “动作” 文件名字

命令 | sed [ 选项] “动作” 文件名字

打印 “p”

会显示两行 一个是原数据 一个是处理完以后的数据

sed "p" /etc/passwd 有两行

sed "p;p" /etc/passwd 多次动作用;间隔

sed "p;=" /etc/passwd = 显示行号

root:x:0:0:root:/root:/bin/bash p打印的内容

1 =显示的内容

root:x:0:0:root:/root:/bin/bash 原数据

bin:x:1:1:bin:/bin:/sbin/nologin

2

bin:x:1:1:bin:/bin:/sbin/nologin

-n 不显示原数据 只显示输出后的结果

[root@xu opt]# sed -n "p" /etc/passwd

打印模几行

[root@xu opt]# sed -n "2,5p" /etc/passwd

[root@xu opt]# sed -n "1p;3p;5p" /etc/passwd

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

删除 d

只删除第一行的显示内容

[root@xu opt]# sed "1d" /etc/passwd

[root@xu opt]# sed "1d;3d" /etc/passwd

起始行 结果行

[root@xu opt]# sed "1,3d" /etc/passwd

加 -i 选项 是操作原文件(慎用)

[root@xu opt]# sed -i "1d" /etc/passwd

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

用正则表达式来删除 必须要用 / / d 格式匹配

[root@xu opt]# sed -n "/xly/,/abc/d" /etc/passwd

从第 2行开始(包括第2行)在往下删去2行

[root@xu ~]# sed "2,+2d" /etc/passwd

从2开始 删掉第一个是5的倍数行之间的行

[root@xu ~]# sed "2,~5d" /etc/passwd

删除偶数行(能除2的) 每2行删去第1行

[root@xu ~]# sed "1~2d" /etc/passwd

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

替换 s “ s / / /gi“ g全局 i忽略大小写

[root@xu ~]# sed -n "s/a/b/gi" /etc/passwd

替换多个范围的 1行到3行

[root@xu ~]# sed -n "1,3s/a/b/gi" /etc/passwd

------

用正则 修改 用// 圈起来

把所有的数字改成字母

[root@xu ~]# sed -n "s/[0-9]/b/g" /etc/passwd

把包含有字母都删除

[root@xu ~]# sed -n "s/[a-z]//g" /etc/passwd

修改运行级别到3

[root@xu ~]# grep initdefault /etc/inittab

# 0 - halt (Do NOT set initdefault to this)

# 6 - reboot (Do NOT set initdefault to this)

id:5:initdefault:

[root@xu ~]# sed "/id/s/[0-6]/3/" /etc/inittab

#

在sed 的正则表达式里

-r

在正则表达式里 不用转意符 可以用-r 解决

[root@xu ~]# sed -r "/id/s/[0-6]{2}/3/" /etc/inittab

把/etc/passwd 文件里 没一行的第一个字符删掉

[root@xu ~]# sed -n "s/.//" /etc/passwd

把/etc/passwd 文件里 每一行的第一个和最后一个字符删掉

() 保存所匹配的字符 & 代替你查找的所有字符

每一个模式 是\1 \2 ...\9 每个模式对应前面的第几个()里的内容

出现在第一个 是开头 第二个是去掉最后一个的所有内容 的三个是最后一个内容

[root@xu ~]# sed -n -r "s/(.)(.*)(.)/\2/" /etc/passwd

修改ip最后的地址为254

[root@xu opt]# sed -r "s/(192.168.1.)(.*)/\1254/" ip.txt

192.168.1.254

192.168.1.254

192.168.1.254

192.168.1.254

192.168.1.254

192.168.1.254

192.168.1.254

把一个文件所有的大写 字母加上个小括号

[root@xu opt]# sed "s/[A-Z]/(&)/g" /etc/passwd

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

添加 a 默认的是每一行都添加一个

[root@xu opt]# sed -r "aGATEWAY=192.168.1.254" ifcfg-eth0

指定位置添加

[root@xu opt]# sed -r "1aGATEWAY=192.168.1.254" ifcfg-eth0

插入 i 插入到上面

[root@xu opt]# sed -r "1iGATEWAY=192.168.1.254" ifcfg-eth0

替换 c

第一行替换成GATEWAY....

[root@xu opt]# sed -r "1cGATEWAY=192.168.1.254" ifcfg-eth0

导入 r

把有a里的内容 导入到搜索出来1这行的内容的下面

把只要有1的行导入到a.txt里去

什么内容到导入到那里原文件

[root@xu opt]# sed -r "/1/r a.txt" 1.txt

导出 w

把有a的内容写到 1.txt里去 会覆盖之前的内容

把只要有a的导出到1.txt里

[root@xu opt]# sed -r "/a /w 1.txt" a.txt

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

命令组

root@xu opt]# sed -n "2=;2p" a.txt

[root@xu opt]# sed -n "2{=;p}" a.txt

-e 如果有多个命令要执行的时候 可以加多个 -e 连起来 作成一个命令组

[root@xu opt]# sed -n -e "2=" -e "2p" a.txt、

除了第一行剩下的内容 取反

[root@xu opt]# sed -n "1 ! p" 2.txt

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

删出 d

[root@xu opt]# sed "d" a.txt

4n 把当前行 读出下一行 也就是 第4行不读 其他的 都读

[root@xu opt]# sed "4n;d" a.txt

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

sed 复制

有俩个空间 sed的缓存

一个是模式空间 里面不存数据

当sed 处理一个流的时候 他会把他放到 里买 处理的时候拿进来 处理完了拿出去

二个是保持空间

默认情况下什么都没有 只有一个换行符\n

俩个选项

剪贴

H 追加导入到保持空间

h 覆盖导入到保持空间

[root@xu opt]# sed "1h;1d;5G" 2.txt

粘贴

G 追加粘贴到模式空间

g 覆盖粘贴到模式空间

[root@xu opt]# sed "1H;5G" 2.txt

[root@xu opt]# sed "1,3h;5G" 2.txt

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

awk 单独的一门语言 也是逐行处理

awk 的格式

awk [选项] “动作” 文件名

命令 | awk [选项] “动作” 文件名

awk -F":" '{print FILENAME}'

位置变量 第一列的值就是$1

$1 。。。$n 分割

$0 代表整个行的信息

位置变量

[root@xu opt]# awk -F":" '{print $1,$2}' /etc/passwd

[root@xu opt]# head /etc/passwd | awk -F":" '{print $1,$2}'

打印当前文件名 FILENAME

[root@xu opt]# awk -F":" '{print FILENAME}' /etc/passwd

打印分割类的个数 NF

[root@xu opt]# awk -F":" '{print NF}' /etc/passwd

当前处理行的行数 NR

[root@xu opt]# awk -F":" '{print NR}' /etc/passwd

处理当前行在文件内的行数FNR

[root@xu opt]# awk -F":" '{print FNR}' /etc/passwd

AWK的默认分隔符 为空格 和 tab键默认时可以省略 -F

[root@xu opt]# head -3 /etc/passwd | awk -F":" '{print $1,$3,$4}'

root 0 0

bin 1 1

daemon 2 2

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

awk 处理数据的时候顺序是三个 行前 行中 行后

行前

BEGIN{}

[root@xu opt]# awk -F":" 'BEGIN{print NR}' /etc/passwd

0

行中

{}

[root@xu opt]# awk -F":" '{print NR}' /etc/passwd

行后的

END{}

[root@xu opt]# awk -F":" 'END{print NR}' /etc/passwd

73

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

用正则

awk '条件{print NR}'

~ 匹配

!~ 不匹配

匹配是root的

[root@xu opt]# awk -F ":" '$1~/root/{print $1}' /etc/passwd

root

比较符号

= == != > >= < <=

逻辑比较 || &&

运算符号

+ - * / % += -= *= /=

i=5

i+=2

i=i+2

i=7

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

awk流程控制

流程控制

分支结构

if (条件) 动作

若有多个动作,则要用大括号将动作体包含起来

if (条件) {动作 1;动作 2}

# awk -F : '{if ($1 == "root") print $1}' /etc/passwd

# awk -F: '{if ($1 == "root") {print $1;print $6} }' /etc/passwd

if (条件 1)

动作 1

else

动作 2

# awk -F: '{if ($1 == "root"){print $1}else print $6}' /etc/passwd

# awk -F: '{if ($1 == "root") print $1;else print $6}' /etc/passwd

上面两个命令是等价的 ,要么用分号隔开 ,表示第一个动作体的结束 ,要么将动作体用大括号定位范围

if (条件 1)

动作 1

else if(条件 2)

动作 2

else if(条件 3)

动作 3

else

动作 4

# awk -F: '{if ($1 == "root") print $1;else if ($1 == "seker") print $6;else if ($1 == "zorro") print $7;else print

NR}' /etc/passwd

条件 ? 动作 1 : 动作 2

Expr ? action1 : action2

# awk -F: '{print ($3<5?$1:$3)}' /etc/passwd

读前处理和读后处理

# awk -F: 'BEGIN {print NR,NF}' /etc/passwd

00

# awk -F: 'END {print NR,NF}' /etc/passwd

46 7

# awk -F: 'BEGIN{i=1} {i++} END {print i}' /etc/passwd

47

练习 找出普通用户的用户名并统计数量

#awk -F: 'BEGIN{i=0} $3>=500 {print $1;i++} END {print i}' /etc/passwd

循环语句

while(条件) {

动作

条件运算

}

# awk -F: '{while($3<3) {print $3,$1;$3++}}' /etc/passwd

BEGIN

BEGIN 块可以独立使用,不需要引入文件

# awk 'BEGIN{i=1;while(i<100) {print i;i++}}'

练习 打印 100 以内的偶数

# awk 'BEGIN{i=1;while(i<100) {if (i%2==0) print i;i++}}'

x=1

do {

动作 1

x++

} while (x<5)

# awk 'BEGIN{i=5;do{print i;i++}while(i<10)}'

# awk 'BEGIN{i=5;do{print i;i++}while(i<1)}'

for(预置;条件;递增) {

动作

}

# awk 'BEGIN {for (x=1;x<=4;x++) print x }'

输出样式

# awk -F: '{printf "%-10s %-10d %s\n",$1,$3,$7}' /etc/passwd

%s 字符类型, %d 数值类型

printf 默认是不输出换行的所以要加\n

10 和 7 是偏移量

默认是右对齐,所有加个- 就是左对齐,就是把不足的位数用空格填充

注意:格式与输出列之间要有逗号

跳转语句

break 跳出循环

# awk 'BEGIN {for(x=1;x<5;x++) {if (x==3) break;print x }}'

1

2

continue 在达到循环底部之前终止当前循环 从新开始下一次循环

# awk 'BEGIN {for(x=1;x<5;x++) {if (x==3) continue;print x }}'

1

2

4

next 读入下一行 同时返回脚本顶部 这样可以避免对当前行执行其他操作

# awk -F: 'NR > 5 {next} {print $1} END {print NR}' /etc/passwd

root

bin

daemon

adm

lp

46

46

#

exit 使读取动作终止 并将控制移动到 END,如果没有 END 则终止脚本

# awk -F: 'NR > 5 {exit} {print $1} END {print NR}' /etc/passwd

root

bin

daemon

adm

lp

6

[root@svr10 pub]# cat -b u.txt

1 root:x:0:0:root:/root:/bin/bash

2 bin:x:1:1:bin:/bin:/sbin/nologin

3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

4 adm:x:3:4:adm:/var/adm:/sbin/nologin

5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

6 sync:x:5:0:sync:/sbin:/bin/sync

7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

8 halt:x:7:0:halt:/sbin:/sbin/halt

9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

10 news:x:9:13:news:/etc/news:

[root@svr10 pub]# awk -F: 'BEGIN{i=1}NR>5 {next}{print i++}END{print NR}' u.txt

1

2

3

4

5

10

[root@svr10 pub]# awk -F: 'BEGIN{i=1}NR>5 {exit}{print i++}END{print NR}' u.txt

1

2

3

4

5

6

[root@svr10 pub]#

数组

自定义数组

# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";print ary[1],ary[2]}'

seker zorro

# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";for(i in ary) print ary[i]}'

seker

zorro

#

循环产生数组和取出数组

# awk 'BEGIN{n=5;for (i=1;i<=n;i++) ary[i]=i+100;for(m in ary) print m,ary[m]}'

4 104

5 105

1 101

2 102

3 103

#

# awk -F: '{ary[NR]=$1} END {for(i in ary) print i,ary[i]}' /etc/passwd

1 root

2 bin

3 daemon

4 adm

5 lp

6 sync

7 shutdown

8 halt

9 mail

# awk -F: '{ary[$3]=$1} END {for(i in ary) print i,ary[i]}' /etc/passwd

10 uucp

11 operator

12

12 games

13 gopher

14 ftp

32 rpc

37 rpm

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值