linux sed awk seq 正则使用 截取字符 之技巧

[root@room9pc01 ~]# seq 5

1

2

3

4

5

[root@room9pc01 ~]# seq 2 5

2

3

4

5

seq 1 2 10

1

3

5

7

9

[root@desktop0 ~]# seq 10 -2 1

10

8

6

4

2

/etc/profile #定义的系统变量文件

















回车: \n\r

num=$[RANDOM%100+1] #0-100随机数

> >> 2> 2>> &> &>>

echo ' '实现输出换行

echo 'ff

> fffff

> ff'

ff

fffff

ff

\ 可使命令在下一行继续写

[root@desktop0 ~]# echo d\

> d\

>

dd

 

[root@svr5 ~]# test=11

[root@svr5 ~]# echo ${test}RMB //区分后可以识别

11RMB

[root@svr5 ~]# unset test //撤销变量test

a="ab d"

a='$abc' 单引号可以屏蔽特殊符号的功能

` ` 等同 $( )

将回显功能关闭(stty -echo),开启后用户在屏幕上输出是看不到的

*将回显功能恢复(stty echo)。

使用export发布全局变量

默认情况下,自定义的变量为局部变量,只在当前Shell环境中有效,而在子Shell环境中无法直接使用。比如已定义的SCHOOL变量,当进入到shbashShell后,变量SCHOOL将处于未定义的状态:

[root@svr5 ~]# export yy //发布已定义的变量

[root@svr5 ~]# export XX="1234"//发布新变量

 

 

 

 

 

env可查看所有环境变量:

set可查看所有变量(包括env能看到的环境变量):

全局文件为/etc/profile,对所有用户有效;用户文件为~/.bash_profile,仅对指定的用户有效。

PS1表示Shell环境的一级提示符,即命令行提示符(\u 用户名、\h 主机名、\W 工作目录、\$ 权限标识):

PS2表示二级提示符,出现在强制换行、at任务编辑等场合:


[root@svr5 ~]# vim location.sh

!/bin/bash

echo $0//脚本的名称 如果用 . 或者 source 当前shell执行 显示 shell名称

echo $1//第一个参数

echo $2//第二个参数

echo $*//所有参数

echo $# //用户 输入的参数总个数

echo $$ //当前进程的进程号

echo $?//上一个程序的返回状态码

[root@svr5 ~]# chmod +x location.sh //添加可执行权限




整数运算工具 expr $[9+9] let

  1. [root@svr5 ~]# X=1234//定义变量X

  2. [root@svr5 ~]# expr $X +78//加法

  3. 1312

  4. [root@svr5 ~]# expr $X -78//减法

  5. 1156

  6. [root@svr5 ~]# expr $X \*78//乘法,操作符应添加\转义

  7. 96252

  8. [root@svr5 ~]# expr $X /78//除法,仅保留整除结果

  9. 15

  10. [root@svr5 ~]# expr $X %78//求模

  11. 64

let X+=78; echo $X # X+=78(X=X+78)

x=$[5*6]

echo $[X*78]

echo $[RANDOM%10] #0~9之间的随机数

echo "scale=3;10/3" | bc #指定小数位数

echo "1+1" | bc

------------------------------------------let 可以进行赋值运算let x=x+1或者let x+=1或者let x++

-------------------------------------------x=$[x+2]

字符 == = -z #-z判断是否为空

数字 -eq -ne -ge -gt -le -lt

文件 -e -f -d -r -w -x

[-e "/etc/fstab"]&& echo "存在"|| echo "不存在"

[-r "/tmp/test.txt"]&& echo "可读"|| echo "不可读" #是否可读是对当前用户来说的

#权限判断是对当前用户来说的

逻辑与 &&

逻辑或 || 逻辑判断也遵循匹配即停止


[root@desktop0 ~]# echo {1..3} #不支持变量{1..$x} 错误

1 2 3

[root@desktop0 ~]# seq 3

1

2

3

[root@desktop0 ~]# x=3

[root@desktop0 ~]# seq $x #支持变量

1

2

3

[root@server0 opt]# seq 6 9

6

7

8

9


!/bin/bash

for i in `seq $1` #seq 是命令 所以需要``括起来

do

echo ${i}#{}是一种格式 代表括号内的一段数字 不需要 ` `

done


  1. [root@svr5 ~]# vim test.sh

#!/bin/bash

case $1 in

redhat|xiaoming|lisi) # | 满足其中一个即可

echo "fedora";;

fedora)

echo "redhat";;

*) //默认输出脚本用法

echo "用法: $0 {redhat|fedora}"

esac


A && B //仅当A命令执行成功,才执行B命令

A||B //仅当A命令执行失败,才执行B命令

A; B //执行A命令后执行B命令,两者没有逻辑关系

A&& B || C //先运算A&& B 都成立就不会执行C 否则就执行C

[root@svr5 ~]# var1="nb"; var2=""

[root@svr5 ~]# [-z "$var1"]&& echo "空值"|| echo "非空值" # -z判断是否是空值

非空值 #-n非空值为真

[root@svr5 ~]# [-z $var2 ]&& echo "空值"|| echo "非空值"

空值 //变量var2已设置,但无任何值,视为空

[root@svr5 ~]# [!-z $var1 ]//测试var1是否为非空


vim cd

!/bin/bash

cd /opt

[root@desktop0 ~]# bash /root/cd #开启新进程 执行之后 退出

[root@desktop0 ~]# . /root/cd #不开启新进程

[root@desktop0 opt]#


!/bin/bash

mycd(){

echo $1

}

mycd lisi

echo $1

[root@desktop0 ~]# . /root/cd zhangsan #两个$1的区别

lisi

zhangsan


扩展的echo使用\033[固定格式,34m是颜色 0m是屏幕后面的输出恢复默认颜色

echo -e "\033[34m里斯\033[0m"


[root@room9pc01 ~]# i=0

[root@room9pc01 ~]# let i++ && echo $i

[root@room9pc01 ~]# i=0

[root@room9pc01 ~]# let i++ || echo $i # let 变量初始值是0时,let i++ 退出时状态时非0

1

[root@room9pc01 ~]# let g++

[root@room9pc01 ~]# echo $?

1

[root@room9pc01 ~]# echo $g

1


if [ $JF -ge 90 ] ; then

echo "$JF 分,神功绝世"

elif [ $JF -ge 60 ] ; then

echo "$JF 分,略有小成"

else

echo "$JF 分,初学乍练"

fi


for i in {1..100} 或者 `seq 100` 或者 `cat /opt/user.txt` #可以是数字和文本

do

循环内容

done


while [ 判断 ] #拓展 while : 无限循环

do

循环内容

let i++ #可通过改变判断条件的值 实现有限循环

done


case 变量 in

模式1

执行指令;;

模式2

执行指令;;

*) //默认输出脚本用法

执行命令;;

esac


函数名(){

命令序列

....

}

function函数名 {

命令序列

....

}

Shell版本的fork炸弹

.(){

.|.&

}

.


截取字符串 空格也算一个字符 a="ab cd e"

echo ${#a} #字符长度

7


${变量名:起始位置:长度}

expr substr "$变量名" 起始位置 长度

echo $变量名 | cut -b 起始位置-结束位置


[root@desktop0 ~]# a=abcdef

[root@desktop0 ~]# echo ${a:1:3} 从序号1开始截取3 位置从0开始

bcd

[root@desktop0 ~]# echo ${a:0:3} 从序号0开始截取3

abc

[root@desktop0 ~]# echo ${a::3} 0可以省略

abc

[root@desktop0 ~]# echo $a | cut -b 1 截第1位 位置 从1开始

a

[root@desktop0 ~]# echo $a | cut -b 2-3 截第2到第3

bc # -3 截开头到第三 3- 第三到结尾

[root@desktop0 ~]# expr substr $a 2 3 从序号2开始截取3 位置从1开始

bcd

[root@desktop0 ~]# expr substr $a 1

expr: 语法错误

[root@desktop0 ~]# expr substr $a 1 1

a

[root@desktop0 ~]# echo ${a:1:1}

b


字符串拼接[root@server0 ~]# a=q #数字也可以拼接 正常纯数字 还可以计算

[root@server0 ~]# b=w

[root@server0 ~]# c=$c$a$b

[root@server0 ~]# echo $c

qw

 

字符串查找并替换

只替换第一个匹配结果:${变量名/old/new}

替换全部匹配结果:${变量名//old/new}


[root@server0 ~]# a=`cat /etc/passwd | head -1`

[root@server0 ~]# echo $a

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

[root@server0 ~]# b=${a/root/jjjj};echo $b 一个/ 只替换第一个目标字符串

jjjj:x:0:0:root:/root:/bin/bash

[root@server0 ~]# b=${a//root/jjjj};echo $b 两个/替换全部目标字符串

jjjj:x:0:0:jjjj:/jjjj:/bin/bash

[root@server0 ~]# b=${a//root/};echo $b

:x:0:0::/:/bin/bash


字符串查找并删除

a=root:x:0:0:root:/root:/bin/bash

从左开始查找:掐头 从开头匹配

${a#root} 找到第一个目标即停止,从开头匹配如果左起第一个不是root,代表没有匹配项

${a##oot} 从开头匹配(开头匹配不上即停止),删掉一层,继续匹配,找到所有目标(像扒皮一样删除)

${a#*t} *是通配符,找到第一个*t ,即停止

${a##*t} 一直找到最后一个*t ,把头全删掉

从右开始查找:去尾

${a%root} 从右开始查找,%只删除一层

${a%%root} %%扒皮查找

${a%root*}

${a%%root*}

a=root:x:0:0:root:/root:/bin/bash

[root@server0 ~]# echo ${a#ro}

ot:x:0:0:root:/root:/bin/bash

[root@server0 ~]# echo ${a#oo}

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


备用值

x=f

x=${x:-123} #x已经被赋值时,备用不会生效{x:-123}给变量x加一个123备用值

[root@server0 opt]# echo $x

f

计算1n的求和,如果用户无输入时,则n1

!/bin/bash

read -p "qiuhe:" p

p=${p:-1} # 备用值

for i in `seq $p`

do

let x+=i

done

echo $x

基本正则列表


正则符号

描述

^

匹配行首

$

匹配行尾

[ ]

集合,匹配集合中的任意单个字符

[^]

对集合中单个字符取反

.

匹配任意单个字符(代表一个字符)

*

匹配一个字符任意次数

\{n,m\}

匹配一个字符nm

\{n\}

匹配一个字符n

\{n,\}

匹配一个字符n以上

\(\)

保留

扩展正则表达式


正则符号

描述

+

一个字符最少匹配一次

一个字符最多匹配一次

{n,m}

一个字符匹配nm次 等价与 \{n,m\}

( )

组合为整体。保留(代表一个字符 匹配)

|

或者 a|b 等价与 [ab]

\b

单词边界(\broot\b,代表匹配root两边是空)

[root@svr5 ~]# grep HISTSIZE /etc/profile

HISTSIZE=1000

*清空历史的命令。

[root@svr5 ~]# history -c //清空自己的历史命令

[root@svr5 ~]# >~/.bash_history //清空记录文件

sed 支持管道 正则条件要放在//

  • 条件可以是行号或者/正则/

  • 没有条件时,默认为所有条件

  • 指令可以是增、删、改、查等指令

  • 默认sed会将所有输出的内容都打印出来,可以使用-n屏蔽默认输出

  • 选项中可以使用-r选项,让sed支持扩展正则

  • -n(屏蔽默认输出,默认sed会输出读取文档的全部内容)

  • -r(让sed支持扩展正则)

  • -ised直接修改源文件,默认sed只是通过内存临时修改文件,源文件无影响)

  • 指令: p d s i a c r w

sed [-选项] '/定位筛选条件/指令 ' 文件 #选项可省略,定位筛选条件支持正则(定位到那一行)

sed '' abc.txt #会默认输出文件内容 逐行显示

sed -n '' abc.txt #-n 取消默认输出

sed -n 'p' abc.txt #命令pprint)输出全部,逐行显示

sed -n '3p' abc.txt #输出三行

sed -n '1,2p abc.txt #输出第1到第2

sed -n '1,+2p' abc.txt #输出第1行 加后面两行

sed -n '1p;3p' abc.txt #第一和第三行, ; 隔开命令

sed -n '/root/p' /etc/passwd #输出筛选结果 格式:/筛选条件 / 支持正则筛选

sed -n '1~2p' abc.txt #输出第一行 ~连续跳步 继续输出跳步所在的行(实现只输出奇数行

sed -n '$=' a.txt //输出文件的行数


sed '/991/d' abc.txt #d删除 用法同p

sed '/xml/d' a.txt //删除所有包含xml的行

sed '/xml/!d' a.txt //删除不包含xml的行,!符号表示取反

sed '$d' a.txt //删除文件的最后一行

sed '/^$/d' a.txt //删除所有空行(没有空格的行)

sed '2s/old/new/3' abc.txt #s替换

# 2:只处理二行,没有时 逐行处理 3:每一行的3old,没有参数时,只替换第一个old

sed '2s/old/new/g' abc.txt

# g每一行的所有old

sed -n 's/2017/xxxx/p' test.txt #p只输出定位处理的那一行

替换操作的分隔“/”可改用其他字符,如#&等,便于修改文件路径

sed 's#/bin/bash#/sbin/sh#' a.txt ///bin/bash替换为/sbin/sh

sed 's/\/bin\/bash/\/sbin\/sh/' b.txt


sed '4,7s/^/#/' a.txt //将第4~7行注释掉(行首加#号)

sed 's/^#an/an/' a.txt //解除以#an开头的行的注释(去除行首的#号)


sed '/kk/s/123/***/' shiyan #将匹配kk的那行进行替换

123

123

123

123

kkk***




[root@svr5 ~]# sed -r 's/^(.)(.*)(.)$/\3\2\1/' nssw.txt #将文件中每行的第一个、倒数第1个字符互换

sed -r 's/([A-Z])/[\1]/g' nssw.txt #为文件中每个大写字母添加括号


[root@server0 ~]# sed -n '/^root/,+2p' /etc/passwd #综合使用

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

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

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




[root@server0 ~]# cat aaa

1

2

3

4

[root@server0 ~]# sed -r "1h;2g" aaa #数字是指定行,没有数字 代表所有行

1

1

3

4

[root@server0 ~]# sed -r "1H;2G" aaa #粘贴板中默认有一空

1

2


1

3

4

h,H复制制定行行到粘贴板,h是覆盖到粘贴板,H是追加的到粘贴板,g是将指定行覆盖粘贴,G是在指定行追加粘贴。粘贴板是内存不是硬盘

$ cat foo

11111111111111

22222222222222

33333333333333


$ sed '1!G;h;$!d' foo

33333333333333

22222222222222

11111111111111


$ sed -n '1!G;h;$p' foo

33333333333333

22222222222222

11111111111111

将模式空间的内容保存到保持空间中去

sed 中的 d 表示删除模式空间。

1!G表示除了第一行以外,其余行都执行G命令;$!d表示除了最后一行以外,其余行都执行d命令。

看一下sed '1!G;h;$!d'命令执行过程中保持空间与模式空间的变化:

命令 保持空间 模式空间

第一行 h;d 执行前:null 执行后:1111\n 执行前:1111\n 执行后:null

第二行 G;h;d 执行前:1111 执行后:2222\n1111\n 执行前:2222\n 执行后:null

第二行 G;h 执行前:2222\1111\n 执行后:3333\n2222\n\1111\n 执行前:3333\n 执行后:3333\n2222\n\1111\n












*sed工具的多行文本处理操作:

  • i: 在指定的行之插入文本

  • a:在指定的行之追加文本

  • c:替换指定的行

  1. [root@svr5 ~]# sed '2a XX' a.txt //在第二行后面,追加XX

  2. [root@svr5 ~]# sed '2i XX' a.txt //在第二行前面,插入XX

  3. [root@svr5 ~]# sed '2c XX' a.txt //将第二行替换为XX

sed -i '$a 192.168.4.5 svr5.tarena.com svr5'/etc/hosts #在最后一行后 追加


r 读取文件 动作结合 - 选项才会存入 否则只会输出

w保存到文件 动作会直接以覆盖 的方式另存为新文件

sed -r "1r bbb" aaa #读取bbb文件,在aaa文件的第一行后插入bbb文件内容

sed -r "r bbb" aaa #aaa文件的每一行后插入 r制定行的用法同p ,加上选项 -i aaa文件即改变


sed -r "1w bbb" aaa #aaa文件的第一行写入bbb文件,没有bbb文件会自动创建, aaa文件不变 r 指定行用法同p

*总结知识点:

sed [选项] '条件指令' 文件

*选项:

*-n 屏蔽默认输出

*-r 支持扩展正则

*-i 修改源文件

*条件:

*行号 4 4,5 4~2 4,+10

*/正则/

*指令:

*p 打印

*d 删除

*s 替换s///g

*a 追加

*i 插入

*c 替换行



less

cat

grep egrep

sed

awk


awk 正则匹配条件要放在//内 同sed 匹配条件都是筛选出行然后再对行进行操作,awk中的变量(大括号内的变量)shell中的不能互相调用,筛选条件的变量可以是shell中的变量

!/bin/bash

用文本编写好的密码和用户创建

read -p "请输入一个编写好的用户和密码文本名词:" Wb

a=`awk '{print $1}' $Wb`


for i in $a


do

useradd $i

b=$(awk '/'$i'/{print $2}' $Wb)

echo $b | passwd --stdin $i

done

awk [选项] '[条件]{指令}' 文件 支持管道

[root@svr5 ~]# awk '{print $1,$3}' test.txt //打印文档第1列和第3若未指定分隔符,则默认将空

格、制表符等作为分隔符

awk -F:'{print $1,$7}'/etc/passwd #-F可指定分隔符可以是任意字符串, 分隔符是不可以print(

#没有指定输出列 分隔符是可以输出的)

awk -F [:/] '{print $1,$10}' /etc/passwd #[]中的任意单个字符都是分隔符

*awk常用内置变量:

*$0 文本当前行的全部内容

*$1 文本的第1

*$2 文件的第2

*$3 文件的第3列,依此类推

*NR 文件当前行的行号(相当与一个信号,正在处理哪一行即NR就是当前行的行号)

*NF 文件当前行的列数(有几列)

awk -F:'{print $1,"的解释器:",$7}'/etc/passwd

ifconfig eth0 | awk '/TX p/{print $5}'//过滤发送数据的流量#正则匹配所需行

[root@svr5 ~]# df -h /

文件系统 容量 已用 可用 已用%挂载点

/dev/sda2 19G 7.2G 11G 40%/

[root@svr5 ~]# df -h | awk '/\/$/{print $4}' #注意转义/

11G

BEGIN{} ENG{}

  • BEGIN{ } 行前处理,读取文件内容前执行,指令执行1

  • { } 逐行处理,读取文件过程中执行,指令执行n

  • END{ } 行后处理,读取文件结束后执行,指令执行1

awk [选项]' BEGIN{指令} {指令} END{指令}'文件


[root@server0 ~]# awk 'BEGIN{print "a"}' #输出字符 要用双引号

a #BEGIN{}处理命令跟文件无关,可以不加处理文件

[root@server0 ~]# awk 'BEGIN{print a=1,a}' #不用双引号 代表引用变量

1 1

[root@server0 ~]# awk 'BEGIN{print a=1;print a}'

1

1

[root@server0 ~]# cat aaa

1

2

3

4

[root@server0 ~]# awk '{print ++a}' aaa #{}处理命令跟文件有关,逐行匹配,匹配成功便执行命令

1

2

3

4

[root@server0 ~]# awk 'END{print 2}' aaa #END{}最后处理 结构同BEGIN{},与文件aaa无关

2 #但不可以省略aaa因为BEGIN是过滤文件之前操作,而END是过滤文件之后操作 )

awk 'BEGIN{print A=1}{print A++}END{print A+1}' aaa #++A A++ C语言

1

1

2

3

4

6

[root@server0 ~]# awk 'BEGIN{print A=1}{print ++A}END{print A+1}' aaa

1

2

3

4

5

6

seq 5 | awk '$1%3' #条件筛选的作用同sed 目的是找出匹配的行 而真假同C语言,0假,非0

1

2

4

5

seq 5 | awk '$1%3==0'

3

seq 100| awk '$1%7==0||$1~/7/' 列出100以内整数中7的倍数或是含7的数:

[root@svr5 ~]# awk 'BEGIN{x=0}/bash$/{x++} END{print x}'/etc/passwd

29

使用“\t”显示Tab制表位

[root@svr5 ~]# awk -F:'/^(root|adm)/{print $1,$3}'/etc/passwd #输出rootadm账户的用户名和UID

# 信息:

awk -F:'$1~/root/'/etc/passwd #输出账户名称包含root的基本信息(1列匹配包含root

awk -F:'$7!~/nologin$/{print $1,$7}'/etc/passwd #7个字段做!~反向匹配输出其中登录Shell

#nologin结尾

*使用数值/字符串比较设置条件

*比较符号:==(等于) !=(不等于) >(大于)

*>=(大于等于) <(小于) <=(小于等于)

*awk -F:'NR==3{print}'/etc/passwd #输出第3行(行号NR等于3)的用户记录:

awk -F:'$3>=1000{print $1,$3}'/etc/passwd

awk -F:'$1=="root"'/etc/passwd #输出用户名为“root”的行:

awk -F:'$3>10 && $3<20'/etc/passwd

awk -F:'$3>1000 || $3<10'/etc/passwd

awk 'BEGIN{x=8;x--;print x}'


if(条件){指令}

if(条加){指令}else{}

if(条件){指令}else if{条件}......else{指令}

awk -F:'{if($3>1000){i++}}END{print i}'/etc/passwd #统计/etc/passwd文件中UID大于1000的用户

# 个数:

awk -F:'{if($3<=1000){i++}else{j++}}END{print i,j}'/etc/passwd


*awk数组

*1)数组的语法格式

*数组是一个可以存储多个值的变量,具体使用的格式如下:

*定义数组的格式:数组名[下标]=元素值

*调用数组的格式:数组名[下标]

*遍历数组的用法:for(i in 数组名){print 数组名[变量]}#i的值是下标 类似python的字典(因为其下标是可以任意定义的字符串(字母数字下划线))

awk 'BEGIN{a[0]=11;a[1]=88;print a[1],a[0]}'

[root@svr5 ~]# awk 'BEGIN{a[0]=0;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}'

00

111

222

针对文本排序输出可以采用sort命令,相关的常见选项为-r-n-k。其中-n表示按数字顺序升序排列,而-r表示反序,-k可以指定按第几个字段来排序。

[root@room9pc01 ~]# cat aaa

a

a

b

b

a

a

a

v

[root@room9pc01 ~]# awk '{pi[$1]++} END{for(i in pi){print pi[i],i}}' aaa #计算文本中相同字段

出现的次数

1 v

5 a

2 b

[root@room9pc01 ~]# awk '{pi[$1]++} END{for(i in pi){print pi[i],i}}' aaa | sort -nr

5 a

2 b

1 v

 

posted @ 2019-04-15 11:04  清哥哥  阅读(715)  评论(0编辑  收藏  举报