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变量,当进入到sh或bash子Shell后,变量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
-
[root@svr5 ~]# X=1234//定义变量X
-
[root@svr5 ~]# expr $X +78//加法
-
1312
-
[root@svr5 ~]# expr $X -78//减法
-
1156
-
[root@svr5 ~]# expr $X \*78//乘法,操作符应添加\转义
-
96252
-
[root@svr5 ~]# expr $X /78//除法,仅保留整除结果
-
15
-
[root@svr5 ~]# expr $X %78//求模
-
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
-
[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
计算1到n的求和,如果用户无输入时,则n为1
!/bin/bash
read -p "qiuhe:" p
p=${p:-1} # 备用值
for i in `seq $p`
do
let x+=i
done
echo $x
基本正则列表
正则符号 |
描述 |
^ |
匹配行首 |
$ |
匹配行尾 |
[ ] |
集合,匹配集合中的任意单个字符 |
[^] |
对集合中单个字符取反 |
. |
匹配任意单个字符(代表一个字符) |
* |
匹配前一个字符任意次数 |
\{n,m\} |
匹配前一个字符n到m次 |
\{n\} |
匹配前一个字符n次 |
\{n,\} |
匹配前一个字符n次以上 |
\(\) |
保留 |
扩展正则表达式
正则符号 |
描述 |
+ |
前一个字符最少匹配一次 |
? |
前一个字符最多匹配一次 |
{n,m} |
前一个字符匹配n到m次 等价与 \{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支持扩展正则)
-
-i(sed直接修改源文件,默认sed只是通过内存临时修改文件,源文件无影响)
-
指令: p d s i a c r w
sed [-选项] '/定位筛选条件/指令 ' 文件 #选项可省略,定位筛选条件支持正则(定位到那一行)
sed '' abc.txt #会默认输出文件内容 逐行显示
sed -n '' abc.txt #-n 取消默认输出
sed -n 'p' abc.txt #命令p(print)输出全部,逐行显示
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:每一行的第3个old,没有参数时,只替换第一个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:替换指定的行
-
[root@svr5 ~]# sed '2a XX' a.txt //在第二行后面,追加XX
-
[root@svr5 ~]# sed '2i XX' a.txt //在第二行前面,插入XX
-
[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 #输出root或adm账户的用户名和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