| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 开发工具 -> Shell脚本 & Sed流编辑器 & awk语法 -> 正文阅读 |
|
[开发工具]Shell脚本 & Sed流编辑器 & awk语法 |
Shell脚本 & Sed流编辑器 & awk语法参考 文章目录shell脚本一、什么是shell脚本?
简单来说就是将需要执行的命令保存到文本中,按照顺序执行。它是解释型的,意味着不需要编译。
若干命令 + 脚本的基本格式 + 脚本特定语法 + 思想= shell脚本 1、什么时候用到脚本?(★★★)重复化、复杂化的工作,通过把工作的命令写成脚本,以后仅仅需要执行脚本就能完成这些工作。 … 2、shell脚本能干啥?(★★★)①自动化软件部署 LAMP/LNMP/Tomcat… ②自动化管理 系统初始化脚本、批量更改主机密码、推送公钥… ③自动化分析处理 统计网站访问量 ④自动化备份 数据库备份、日志转储… ⑤自动化监控脚本 3、如何学习shell脚本?(★★★)
4、学习shell脚本的秘诀多看(看懂)——>模仿(多练)——>多思考(多写) 5、shell脚本的基本写法1)脚本第一行,魔法字符==#!==指定解释器【必写】
注意: 如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题,所以可以使用: 2)脚本第二部分,注释(#号)说明,对脚本的基本信息进行描述【可选】
3)脚本第三部分,脚本要实现的具体代码内容 6、shell脚本的执行方法(★★★)
小试牛刀: 写一个木有灵魂的脚本,要求如下:
二、变量的定义1、变量是什么?一句话概括:变量是用来临时保存数据的,该数据是可以变化的数据。 2、什么时候需要定义变量?
3、变量如何定义?(★★★)变量名=====变量值 变量名:用来临时保存数据的 变量值:就是临时的可变化的数据
4、变量的定义规则虽然可以给变量(变量名)赋予任何值;但是,对于变量名也是要求的! 1)变量名区分大小写(★★★)
2)变量名不能有特殊符号(★★★)
3)变量名不能以数字开头(★★★)
4)等号两边不能有任何空格(★★★)
5)变量名尽量做到见名知意
5、变量的定义方式有哪些?(★★★)1)直接赋值
2)命令执行结果赋值给变量
3)交互式定义变量(read)目的: 让用户自己给变量赋值,比较灵活。 语法: 常见选项:
举例说明:
用法2:读取来自文件的变量值
4)定义有类型的变量(declare)目的: 给变量做一些限制,固定变量的类型,比如:整型、只读 用法: 常用选项:
举例说明:
6、变量的分类1)本地变量
2)环境变量(★★★)1)按生效的范围分类。
2)按生存周期分类。
环境变量 (也是和程序绑定的, 程序结束时, 动态设置的环境变量也就结束):当前进程有效,并且能够被子进程调用, 反之不行(子进程环境变量的设置对父进程无效)。
3)全局变量(★★★)
说明: 以上文件修改后,都需要重新source让其生效或者退出重新登录。
4)系统变量
./02.sh a b c -> (3个参数)
三、变量的四则运算算术运算:默认情况下,shell就只能支持简单的整数运算 运算内容:加(+)、减(-)、乘(*)、除(/)、求余数(%) 1、四则运算符号(★★★)
2、了解i和i++
四、普通数组和关联数组1、数组分类
2、普通数组定义(★★★)
3、数组的读取(★★★)
4、关联数组定义(★★★)1)首先声明关联数组
2)关联数组赋值
五、变量其他常见操作1、获取目录和文件字符串
2、变量"内容"的删除和替换
替换:
六、条件判断语法结构1、条件判断3种语法格式(★★★)
Note: | 表达式 | 左右两边空格 | 字符串是否需加"" | 是否支持&&和|| | 是否支持C风格 | 2、条件判断的相关参数1)条件判断常用场景判断文件类型,判断文件新旧,判断字符串是否相等,判断权限等等… 2)文件类型判断
举例说明:
3)文件权限判断
4)文件新旧比较说明:这里的新旧指的是文件的修改时间。
5)整数比较(★★★)
6)字符串比较(★★★)
7)逻辑运算符(★★★)
3、条件判断参数的举例说明1)数值比较
2)类C风格的数值比较
3)字符串比较
4)
|
元字符 | 功能 | 备注 |
---|---|---|
. | 匹配除了换行符以外的任意单个字符 | |
* | 前导字符出现0次或连续多次 | |
.* | 任意长度字符 | ab.* |
^ | 行首(以…开头) | ^root |
$ | 行尾(以…结尾) | bash$ |
^$ | 空行 | |
[] | 匹配括号里任意单个字符或一组单个字符 | [abc] |
[^] | 匹配不包含括号里任一单个字符或一组单个字符 | [^abc] |
^[] | 匹配以括号里任意单个字符或一组单个字符开头 | ^[abc] |
^[^] | 匹配不以括号里任意单个字符或一组单个字符开头 | ^[^abc] |
# cat 1.txt
ggle
gogle
google
gooogle
goooooogle
gooooooogle
taobao.com
taotaobaobao.com
jingdong.com
dingdingdongdong.com
10.1.1.1
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,
hello world
helloworld yourself
$ grep ^goo reg_test.txt
google
gooogle
goooooogle
gooooooogle
$ grep ^[goo] reg_test.txt
ggle
gogle
google
gooogle
goooooogle
gooooooogle
$ grep com$ reg_test.txt
taobao.com
taotaobaobao.com
jingdong.com
dingdingdongdong.com
元字符 | 功能 | 备注 |
---|---|---|
\< | 取单词的头 | \<hel 匹配hello world ,hello yourself |
\> | 取单词的尾 | world\> 匹配hello world ,hello yourself |
\< \> | 精确匹配 | |
\{n\} | 匹配前导字符连续出现n次 | go\{3\} 匹配gooogle ,goooooogle ,gooooooogle |
\{n,\} | 匹配前导字符至少出现n次 | |
\{n,m\} | 匹配前导字符出现n次与m次之间 | |
\( \) | 保存被匹配的字符 | |
\d | 匹配数字(grep -P) | [0-9] |
\w | 匹配字母数字下划线(grep -P) | [a-zA-Z0-9_] |
\s | 匹配空格、制表符、换页符(grep -P) | [\t\r\n] |
举例说明:
首先文本内容如下:
# cat 1.txt
ggle
gogle
google
gooogle
goooooogle
gooooooogle
taobao.com
taotaobaobao.com
jingdong.com
dingdingdongdong.com
10.1.1.2.1.1
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,
hello world
helloworld yourself
需求:匹配单词的头和尾
$ grep '\<hel' reg_test.txt
hello world
helloworld yourself
$ grep 'world\>' reg_test.txt
hello world
helloworld yoursel
需求:将10.1.1.2.1.1
替换成10.1.1.345.1.678
,参考Linux vim 文本替换 %s/原文/替换文本/g
1)vim编辑器支持正则表达式
# vim 1.txt
:%s#\(10.1.1\).1#\1.254#g 或者
:%s/\(10.1.1\).2.\(1\).1/\1.345.\2.678/g
2)sed支持正则表达式【后面学】
sed -n 's#\(10.1.1\).1#\1.254#p' 1.txt 或者
sed -n 's/\(10.1.1\).2.\(1\)/\1.345\2.678/p' reg_test.txt
10.1.1.254
Note:
分隔符可以使用#
,也可以使用/
。
找出含有10.1.1的行,同时保留10.1.1并标记为标签1
,之后可以使用\1
来引用它。
最多可以定义9个标签,从左边开始编号,最左边的是第一个。
需求:匹配前导字符出现n
次的行
$ grep 'go\{3\}' reg_test.txt #前导字符o连续出现3次
gooogle
goooooogle
gooooooogle
$ grep -E 'go\{3\}' reg_test.txt
#无效果
需求:匹配有数字的行,匹配有制表符,空格的行
$ grep -P '\d' reg_test.txt
10.1.1.1
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,
$ grep -P '\d' reg_test.txt
hello world
helloworld yourself
grep
要使用正则,必须加 -E ,或者 使用egrep
-E
参数)sed
要使用正则,必须加 -r扩展元字符 | 功能 | 备注 |
---|---|---|
+ | 匹配一个或多个前导字符 | bo+ 匹配boo、 bo |
? | 匹配零个或一个前导字符 | bo? 匹配b、 bo |
\ | 或 | |
() | 组字符(看成整体) | (my\ |
{n} | 前导字符重复n次 | |
{n,} | 前导字符重复至少n次 | |
{n,m} | 前导字符重复n到m次 |
举例说明:
grep "root|ftp|adm" /etc/passwd
egrep "root|ftp|adm" /etc/passwd
grep -E "root|ftp|adm" /etc/passwd
grep -E 'o+gle' test.txt
grep -E 'o?gle' test.txt
# egrep 'go{2,}' 1.txt
# egrep '(my|your)self' 1.txt
使用正则过滤出文件中的IP地址:
# grep '[0-9]\{2\}\.[0-9]\{1\}\.[0-9]\{1\}\.[0-9]\{1\}' 1.txt
10.1.1.1
# grep '[0-9]{2}\.[0-9]{1}\.[0-9]{1}\.[0-9]{1}' 1.txt
# grep -E '[0-9]{2}\.[0-9]{1}\.[0-9]{1}\.[0-9]{1}' 1.txt
10.1.1.1
# grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' 1.txt
10.1.1.1
# grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt
10.1.1.1
表达式 | 功能 | 示例 |
---|---|---|
[:alnum:] | 字母与数字字符 | [[:alnum:]]+ |
[:alpha:] | 字母字符(包括大小写字母) | [[:alpha:]]{4} |
[:blank:] | 空格与制表符 | [[:blank:]]* |
[:digit:] | 数字 | [[:digit:]]? |
[:lower:] | 小写字母 | [[:lower:]]{4,} |
[:upper:] | 大写字母 | [[:upper:]]+ |
[:punct:] | 标点符号 | [[:punct:]] |
[:space:] | 包括换行符,回车等在内的所有空白 | [[:space:]]+ |
[root@server shell05]$ grep -E '^[[:digit:]]+' reg_test.txt #以数字开头的行
10.1.1.2.1.1
7kdjfd989KJK;
[root@server shell05]# grep -E '^[^[:digit:]]+' reg_test.txt #不是以数字开头的行
ggle
gogle
google
gooogle
goooooogle
gooooooogle
taobao.com
taotaobaobao.com
jingdong.com
dingdingdongdong.com
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
bSKJjkksdjf878.
cidufKJHJ6576,
hello world
helloworld yourself
[root@server shell05]$ grep -E '[[:lower:]]{4,}' reg_test.txt #开头至少出现4个小写字母的行少
ggle
gogle
google
gooogle
goooooogle
gooooooogle
taobao.com
taotaobaobao.com
jingdong.com
dingdingdongdong.com
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,
hello world
helloworld yourself
把握一个原则,让你轻松搞定可恶的正则符号:
^key
key$
ab*
ab.
ab.*
{n}
,{n,m}
,{n,}
go+
go?
元字符:在正则中,具有特殊意义的专用字符,如: 星号(*)、加号(+)等
前导字符:元字符前面的字符叫前导字符
元字符 | 功能 | 示例 |
---|---|---|
* | 前导字符出现0次或者连续多次 | ab* abbbb |
. | 除了换行符以外,任意单个字符 | ab. ab8 abu |
.* | 任意长度的字符 | ab.* adfdfdf |
[] | 括号里的任意单个字符或一组单个字符 | [abc][0-9][a-z] |
[^] | 不匹配括号里的任意单个字符或一组单个字符 | [^abc] |
^[] | 匹配以括号里的任意单个字符开头 | ^[abc] |
\^[^] | 不匹配以括号里的任意单个字符开头 | |
^ | 行的开头 | ^root |
$ | 行的结尾 | bash$ |
^$ | 空行 | |
\{n\} | 前导字符连续出现n次 | [0-9]{3} |
\{n,\} | 前导字符至少出现n次 | [a-z]{4,} |
\{n,m\} | 前导字符连续出现n-m次 | go{2,4} |
\<\> | 精确匹配单词 | <hello> |
\(\) | 保留匹配到的字符 | (hello) |
+ | 前导字符出现1次或者多次 | [0-9]+ |
? | 前导字符出现0次或者1次 | go? |
`\ | ` | |
() | 组字符 | (hello\ |
\d | perl内置正则 | grep -P \d+ |
\w | 匹配字母数字下划线 |
# vim test.txt
Aieur45869Root0000
9h847RkjfkIIIhello
rootHllow88000dfjj
8ikuioerhfhupliooking
hello world
192.168.0.254
welcome to uplooking.
abcderfkdjfkdtest
rlllA899kdfkdfj
iiiA848890ldkfjdkfj
abc
12345678908374
123456@qq.com
123456@163.com
abcdefg@itcast.com23ed
1、查找不以大写字母开头的行(三种写法)。
grep '^[^A-Z]' 2.txt
grep -v '^[A-Z]' 2.txt
grep '^[^[:upper:]]' 2.txt
2、查找有数字的行(两种写法)
grep '[0-9]' 2.txt
grep -P '\d' 2.txt
3、查找一个数字和一个字母连起来的
grep -E '[0-9][a-zA-Z]|[a-zA-Z][0-9]' 2.txt
4、查找不以r开头的行
grep -v '^r' 2.txt
grep '^[^r]' 2.txt
5、查找以数字开头的
grep '^[0-9]' 2.txt
6、查找以大写字母开头的
grep '^[A-Z]' 2.txt
7、查找以小写字母开头的
grep '^[a-z]' 2.txt
8、查找以点结束的
grep '\.$' 2.txt
9、去掉空行
grep -v '^$' 2.txt
10、查找完全匹配abc的行
grep '\<abc\>' 2.txt
11、查找A后有三个数字的行
grep -E 'A[0-9]{3}' 2.txt
grep 'A[0-9]\{3\}' 2.txt
12、统计root在/etc/passwd里出现了几次
grep -o 'root' 1.txt |wc -l
13、用正则表达式找出自己的IP地址、广播地址、子网掩码
ifconfig eth0|grep Bcast|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
ifconfig eth0|grep Bcast| grep -E -o '([0-9]{1,3}.){3}[0-9]{1,3}'
ifconfig eth0|grep Bcast| grep -P -o '\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}'
ifconfig eth0|grep Bcast| grep -P -o '(\d{1,3}.){3}\d{1,3}'
ifconfig eth0|grep Bcast| grep -P -o '(\d+.){3}\d+'
# egrep --color '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=10.1.1.1
NETMASK=255.255.255.0
GATEWAY=10.1.1.254
# egrep --color '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=10.1.1.1
NETMASK=255.255.255.0
GATEWAY=10.1.1.254
14、找出文件中的ip地址并且打印替换成172.16.2.254
grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt |sed -n 's/192.168.0.\(254\)/172.16.2.\1/p'
15、找出文件中的ip地址
grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt
16、找出全部是数字的行
grep -E '^[0-9]+$' test
17、找出邮箱地址
grep -E '^[0-9]+@[a-z0-9]+\.[a-z]+$'
grep --help:
匹配模式选择:
Regexp selection and interpretation:
-E, --extended-regexp 扩展正则
-G, --basic-regexp 基本正则
-P, --perl-regexp 调用perl的正则
-e, --regexp=PATTERN use PATTERN for matching
-f, --file=FILE obtain PATTERN from FILE
-i, --ignore-case 忽略大小写
-w, --word-regexp 匹配整个单词
要求如下:
参考脚本:
参考:
#!/bin/bash
conf=/etc/httpd/conf/httpd.conf
input_fun()
{
input_var=""
output_var=$1
while [ -z $input_var ]
do
read -p "$output_var" input_var
done
echo $input_var
}
ipaddr=$(input_fun "Input Host ip[192.168.0.1]:")
web_host_name=$(input_fun "Input VirtualHostName [www.test.cc]:")
root_dir=$(input_fun "Input host Documentroot dir:[/var/www/html]:")
[ ! -d $root_dir ] && mkdir -p $root_dir
chown apache.apache $root_dir && chmod 755 $root_dir
echo this is $web_host_name > $root_dir/index.html
echo "$ipaddr $web_host_name" >> /etc/hosts
[ -f $conf ] && cat >> $conf <<end
NameVirtualHost $ipaddr:80
<VirtualHost $ipaddr:80>
ServerAdmin webmaster@$web_host_name
DocumentRoot $root_dir
ServerName $web_host_name
ErrorLog logs/$web_host_name-error_log
CustomLog logs/$web_host_name-access_loh common
</VirtualHost>
end
sed
是Stream Editor(流编辑器)的缩写,简称流编辑器;用来处理文件的。
sed
是一行一行读取文件内容并按照要求进行处理,把处理后的结果输出到屏幕。
总结:
sed
把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会直接修改原文件Sed
主要用来自动编辑一个或多个文件;简化对文件的反复操作,对文件进行过滤和转换操作sed常见的语法格式有两种,一种叫命令行模式,另一种叫脚本模式。
语法格式:sed [options] '处理动作' 文件名
常用选项:
选项 | 说明 | 备注 |
---|---|---|
-e | 进行多项(多次)编辑 | |
-n | 取消默认输出 | 不自动打印模式空间 |
-r | 使用扩展正则表达式 | |
-i | 原地编辑(修改源文件) | |
-f | 指定sed脚本的文件名 |
常见处理动作:以下所有的动作都要在单引号里
动作 | 说明 | 备注 |
---|---|---|
'p' | 打印 | 需要使用-n 取消默认输出 |
'i' | 在指定行之前插入内容(insert) | 类似vim里的大写O |
'a' | 在指定行之后插入内容(append) | 类似vim里的小写o |
'c' | 替换指定行所有内容 | |
'd' | 删除指定行 |
文件准备
# vim a.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@server ~]# sed '' a.txt 对文件什么都不做
[root@server ~]# sed -n 'p' a.txt 打印每一行,并取消默认输出
[root@server ~]# sed -n '1p' a.txt 打印第1行
[root@server ~]# sed -n '2p' a.txt 打印第2行
[root@server ~]# sed -n '1,5p' a.txt 打印1到5行
[root@server ~]# sed -n '$p' a.txt 打印最后1行
'i'
表示在地址定位的上面插入,'a'
在地址定位的下面插入(但不会编辑源文件)
[root@server ~]# sed '$a99999' a.txt 文件最后一行下面增加内容
[root@server ~]# sed 'a99999' a.txt 文件每行下面增加内容
[root@server ~]# sed '5a99999' a.txt 文件第5行下面增加内容
[root@server ~]# sed '$i99999' a.txt 文件最后一行上一行增加内容
[root@server ~]# sed 'i99999' a.txt 文件每行上一行增加内容
[root@server ~]# sed '6i99999' a.txt 文件第6行上一行增加内容
[root@server ~]# sed '/^uucp/ihello' 以uucp开头行的上一行插入内容
'c'
替换指定的整行内容,并不会修改源文件
[root@server ~]# sed '5chello world' a.txt 替换文件第5行内容
[root@server ~]# sed 'chello world' a.txt 替换文件所有内容
[root@server ~]# sed '1,5chello world' a.txt 替换文件1到5号内容为hello world
[root@server ~]# sed '/^user01/c888888' a.txt 替换以user01开头的行
'd'
删除指定的整行内容
[root@server ~]# sed '1d' a.txt 删除文件第1行
[root@server ~]# sed '1,5d' a.txt 删除文件1到5行
[root@server ~]# sed '$d' a.txt 删除文件最后一行
语法:
sed
选项 ‘s/搜索的内容/替换的内容/动作’ 需要处理的文件,其中,s表示search搜索;斜杠/
表示分隔符,可以自己定义;动作一般是打印p
和全局替换g
如果要在源文件上进行修改,则使用
-i
,不要使用-n
和’p’
[root@server ~]# sed -n 's/root/ROOT/p' 1.txt
[root@server ~]# sed -n 's/root/ROOT/gp' 1.txt
[root@server ~]# sed -n 's/^#//gp' 1.txt
[root@server ~]# sed -n 's@/sbin/nologin@itcast@gp' a.txt
[root@server ~]# sed -n 's/\/sbin\/nologin/itcast/gp' a.txt
[root@server ~]# sed -n '10s#/sbin/nologin#itcast#p' a.txt
uucp:x:10:14:uucp:/var/spool/uucp:itcast
[root@server ~]# sed -n 's@/sbin/nologin@itcastheima@p' 2.txt
注意:搜索替换中的分隔符可以自己指定
[root@server ~]# sed -n '1,5s/^/#/p' a.txt 注释掉文件的1-5行内容
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
#daemon:x:2:2:daemon:/sbin:/sbin/nologin
#adm:x:3:4:adm:/var/adm:/sbin/nologin
#lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
命令 | 解释 | 备注 |
---|---|---|
r | 从另外文件中读取内容 | |
w | 内容另存为 | |
& | 保存查找串以便在替换串中引用 | 和()相同 |
= | 打印行号 | |
! | 对所选行以外的所有行应用命令,放到行数之后 | ‘1,5!’ |
q | 退出 |
需求:
在2.txt第3行下插入/etc/hosts文件内容,可用sed '3r /etc/hosts' 2.txt
在2.txt每一行下插入/etc/hosts文件内容,可用sed 'r /etc/hosts' 2.txt
将reg_test2.txt中包含hello
关键字的行写入reg_test3.txt
中,可用sed '/hello/w reg_test3.txt' reg_test2.txt
r 从文件中读取输入行
w 将所选的行写入文件
[root@server ~]# sed '3r /etc/hosts' 2.txt
[root@server ~]# sed '$r /etc/hosts' 2.txt
[root@server ~]# sed '/hello/w reg_test3.txt' reg_test2.txt
cat reg_test3.txt
hello world
helloworld yourself
[root@server ~]# sed '/[0-9]{4}/w a.txt' 2.txt
[root@server ~]# sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/w b.txt' 2.txt
! 对所选行以外的所有行应用命令,放到行数之后
[root@server ~]# sed -n '1!p' 1.txt
[root@server ~]# sed -n '4p' 1.txt
[root@server ~]# sed -n '4!p' 1.txt
[root@server ~]# cat -n 1.txt
[root@server ~]# sed -n '1,17p' 1.txt
[root@server ~]# sed -n '1,17!p' 1.txt
& 保存查找串以便在替换串中引用 \(\)
[root@server ~]# sed -n '/root/p' a.txt
root:x:0:0:root:/root:/bin/bash
[root@server ~]# sed -n 's/root/#&/p' a.txt
#root:x:0:0:root:/root:/bin/bash
# sed -n 's/^root/#&/p' passwd 注释掉以root开头的行
# sed -n -r 's/^root|^stu/#&/p' /etc/passwd 注释掉以root开头或者以stu开头的行
# sed -n '1,5s/^[a-z].*/#&/p' passwd 注释掉1~5行中以任意小写字母开头的行
# sed -n '1,5s/^/#/p' /etc/passwd 注释1~5行
或者
sed -n '1,5s/^/#/p' passwd 以空开头的加上#
sed -n '1,5s/^#//p' passwd 以#开头的替换成空
[root@server ~]# sed -n '/^root/p' 1.txt
[root@server ~]# sed -n 's/^root/#&/p' 1.txt
[root@server ~]# sed -n 's/\(^root\)/#\1/p' 1.txt
[root@server ~]# sed -nr '/^root|^stu/p' 1.txt
[root@server ~]# sed -nr 's/^root|^stu/#&/p' 1.txt
= 打印行号
$ sed -n '/nologin$/=;/nologin$/p' sed_test.txt
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
$ sed -ne '/nologin$/=' -ne '/nologin$/p' sed_test.txt
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
需求:读取到指定行时,不再继续往下读取
$ sed '/daemon/q' sed_test.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sed '5q' 1.txt
sed '/mail/q' 1.txt
sed -r '/^yunwei|^mail/q' 1.txt
[root@server ~]# sed -n '/bash$/p;10q' 1.txt
ROOT:x:0:0:root:/root:/bin/bash
-e
多项编辑
-r
扩展正则
-i
修改原文件
注意:
-ni
不要一起使用
'p'
命令 不要在使用-i
时使用
-i
- 修改源文件 (★★★)cat sed_test.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
sed -i '1,5s/daemon/&123/' sed_test.txt
cat sed_test.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon123:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
-e
- 多项编辑-e 多项编辑
-r 扩展正则
[root@server ~]# sed -ne '/root/p' 1.txt -ne '/root/='
root:x:0:0:root:/root:/bin/bash
1
[root@server ~]# sed -ne '/root/=' -ne '/root/p' 1.txt
1
root:x:0:0:root:/root:/bin/bash
在1.txt文件中的第5行的前面插入“hello world”;在1.txt文件的第8行下面插入“哈哈哈哈”
[root@server ~]# sed -e '5ihello world' -e '8a哈哈哈哈哈' 1.txt -e '5=;8='
sed -n '1,5p' 1.txt
sed -ne '1p' -ne '5p' 1.txt
sed -ne '1p;5p' 1.txt
过滤vsftpd.conf文件中以#开头和空行:
[root@server ~]# grep -Ev '^#|^$' /etc/vsftpd/vsftpd.conf
[root@server ~]# sed -e '/^#/d' -e '/^$/d' /etc/vsftpd/vsftpd.conf
[root@server ~]# sed '/^#/d;/^$/d' /etc/vsftpd/vsftpd.conf
[root@server ~]# sed -r '/^#|^$/d' /etc/vsftpd/vsftpd.conf
过滤smb.conf文件中生效的行:
# sed -e '/^#/d' -e '/^;/d' -e '/^$/d' -e '/^\t$/d' -e '/^\t#/d' smb.conf
# sed -r '/^(#|$|;|\t#|\t$)/d' smb.conf
# sed -e '/^#/d' -e '/^;/d' -e '/^$/d' -e '/^\t$/d' -e '/^\t#/' smb.conf
[root@server ~]# grep '^[^a-z]' 1.txt
[root@server ~]# sed -n '/^[^a-z]/p' 1.txt
过滤出文件中的IP地址:
[root@server ~]# grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt
192.168.0.254
[root@server ~]# sed -nr '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' 1.txt
192.168.0.254
[root@server ~]# grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 2.txt
10.1.1.1
10.1.1.255
255.255.255.0
[root@server ~]# sed -nr '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' 2.txt
10.1.1.1
10.1.1.255
255.255.255.0
过滤出ifcfg-eth0文件中的IP、子网掩码、广播地址
[root@server shell06]# grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' ifcfg-eth0
10.1.1.1
255.255.255.0
10.1.1.254
[root@server shell06]# sed -nr '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' ifcfg-eth0|cut -d'=' -f2
10.1.1.1
255.255.255.0
10.1.1.254
[root@server shell06]# sed -nr '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' ifcfg-eth0|sed -n 's/[A-Z=]//gp'
10.1.1.1
255.255.255.0
10.1.1.254
[root@server shell06]# ifconfig eth0|sed -n '2p'|sed -n 's/[:a-Z]//gp'|sed -n 's/ /\n/gp'|sed '/^$/d'
10.1.1.1
10.1.1.255
255.255.255.0
[root@server shell06]# ifconfig | sed -nr '/([0-9]{1,3}\.)[0-9]{1,3}/p' | head -1|sed -r 's/([a-z:]|[A-Z/t])//g'|sed 's/ /\n/g'|sed '/^$/d'
[root@server shell06]# ifconfig eth0|sed -n '2p'|sed -n 's/.*addr:\(.*\) Bcast:\(.*\) Mask:\(.*\)/\1\n\2\n\3/p'
10.1.1.1
10.1.1.255
255.255.255.0
sed 选项 ‘sed命令或者正则表达式或者地址定位’ 文件名
正则 | 说明 | 备注 |
---|---|---|
'/key/' | 查询包含关键字的行 | sed -n ‘/root/p’ 1.txt |
'/key1/,/key2/' | 匹配包含两个关键字之间的行 | sed -n ‘/adm/,/mysql/p’ 1.txt |
'/key/,x' | 从匹配关键字的行开始到文件第x行之间的行(包含关键字所在行) | sed -n ‘/^ftp/,7p’ |
'x,/key/' | 从文件的第x行开始到与关键字的匹配行之间的行 | |
'x,y!' | 不包含x到y行 | |
'/key/!' | 不包括关键字的行 | sed -n ‘/bash$/!p’ 1.txt |
sed -f sedScript.sh file
★★★)# sed -f scripts.sh file //使用脚本处理文件
建议使用 ./sed.sh file
脚本的第一行写上
#!/bin/sed -f
1,5d
s/root/hello/g
3i777
5i888
a999
p
#执行sed脚本:
sed -f sed_test.sh reg_test.txt #sed_test.sh为sed命令清单,reg_test.txt为要处理的文件
1)脚本文件是一个sed
的命令行清单,包含多条sed commands
。
2)在每行的末尾不能有任何空格、制表符(tab)或其它文本。
3)如果在一行中有多个命令,应该用分号分隔。
4)不需要且不可用引号保护命令
5)#号开头的行为注释
# cat passwd
stu3:x:509:512::/home/user3:/bin/bash
stu4:x:510:513::/home/user4:/bin/bash
stu5:x:511:514::/home/user5:/bin/bash
# cat sed.sh
#!/bin/sed -f
2a\
******************
2,$s/stu/user/
$a\
we inster new line
s/^[a-z].*/#&/
[root@server ~]# cat 1.sed
#!/bin/sed -f
3a**********************
$chelloworld
1,3s/^/#&/
[root@server ~]# sed -f 1.sed -i 11.txt
[root@server ~]# cat 11.txt
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
#daemon:x:2:2:daemon:/sbin:/sbin/nologin
**********************
adm:x:3:4:adm:/var/adm:/sbin/nologin
helloworld
1、正则表达式必须以”/“前后规范间隔
例如:sed '/root/d' file
例如:sed '/^root/d' file
2、如果匹配的是扩展正则表达式,需要使用-r选来扩展sed
grep -E
sed -r
+ ? () {n,m} | \d
注意:
在正则表达式中如果出现特殊字符(^$.*/[]),需要以前导 "\" 号做转义
eg:sed '/\$foo/p' file
3、逗号分隔符
例如:sed '5,7d' file 删除5到7行
例如:sed '/root/,/ftp/d' file
删除第一个匹配字符串"root"到第一个匹配字符串"ftp"的所有行本行不找 循环执行
4、组合方式
例如:sed '1,/foo/d' file 删除第一行到第一个匹配字符串"foo"的所有行
例如:sed '/foo/,+4d' file 删除从匹配字符串”foo“开始到其后四行为止的行
例如:sed '/foo/,~3d' file 删除从匹配字符串”foo“开始删除到3的倍数行(文件中)
例如:sed '1~5d' file 从第一行开始删每五行删除一行
例如:sed -nr '/foo|bar/p' file 显示配置字符串"foo"或"bar"的行
例如:sed -n '/foo/,/bar/p' file 显示匹配从foo到bar的行
例如:sed '1~2d' file 删除奇数行
例如:sed '0-2d' file 删除偶数行 sed '1~2!d' file
5、特殊情况
例如:sed '$d' file 删除最后一行
例如:sed '1d' file 删除第一行
6、其他:
sed 's/.//' a.txt 删除每一行中的第一个字符
sed 's/.//2' a.txt 删除每一行中的第二个字符
sed 's/.//N' a.txt 从文件中第N行开始,删除每行中第N个字符(N>2)
sed 's/.$//' a.txt 删除每一行中的最后一个字符
[root@server ~]# cat 2.txt
1 a
2 b
3 c
4 d
5 e
6 f
7 u
8 k
9 o
[root@server ~]# sed '/c/,~2d' 2.txt
1 a
2 b
5 e
6 f
7 u
8 k
9 o
1、将文件中任意数字替换成空或者制表符
2、去掉文件1-5行中的数字、冒号、斜杠
3、匹配root关键字的行替换成hello itcast,并保存到test.txt文件中
4、删除vsftpd.conf、smb.conf、main.cf配置文件里所有注释的行及空行(不要直接修改原文件)
5、使用sed命令截取自己的ip地址
# ifconfig eth0|sed -n '2p'|sed -n 's/.*addr://pg'|sed -n 's/Bcast.*//gp'
10.1.1.1
# ifconfig eth0|sed -n '2p'|sed 's/.*addr://g'|sed 's/ Bcast:.*//g'
6、使用sed命令一次性截取ip地址、广播地址、子网掩码
# ifconfig eth0|sed -n '2p'|sed -n 's#.*addr:\(.*\) Bcast:\(.*\) Mask:\(.*\)#\1\n\2\n\3#p'
10.1.1.1
10.1.1.255
255.255.255.0
7、注释掉文件的2-3行和匹配到以root开头或者以ftp开头的行
# sed -nr '2,3s/^/#&/p;s/^ROOT|^ftp/#&/p' 1.txt
#ROOT:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
#3daemon:x:2:2:daemon:/sbin:/sbin/nologin
# sed -ne '1,2s/^/#&/gp' a.txt -nre 's/^lp|^mail/#&/gp'
# sed -nr '1,2s/^/#&/gp;s/^lp|^mail/#&/gp' a.txt
1、写一个初始化系统的脚本
1)自动修改主机名(如:ip是192.168.0.88,则主机名改为server88.itcast.cc
a. 更改文件非交互式 sed
`/etc/sysconfig/network`
b.将本主机的IP截取出来赋值给一个变量ip;再然后将ip变量里以.分割的最后一位赋值给另一个变量ip1
2)自动配置可用的yum源
3)自动关闭防火墙和selinux
2、写一个搭建ftp服务的脚本,要求如下:
1)不支持本地用户登录 local_enable=NO
2) 匿名用户可以上传 新建 删除 anon_upload_enable=YES anon_mkdir_write_enable=YES
3) 匿名用户限速500KBps anon_max_rate=500000
仅供参考:
#!/bin/bash
ipaddr=`ifconfig eth0|sed -n '2p'|sed -e 's/.*inet addr:\(.*\) Bcast.*/\1/g'`
iptail=`echo $ipaddr|cut -d'.' -f4`
ipremote=192.168.1.10
#修改主机名
hostname server$iptail.itcast.com
sed -i "/HOSTNAME/cHOSTNAME=server$iptail.itcast.com" /etc/sysconfig/network
echo "$ipaddr server$iptail.itcast.cc" >>/etc/hosts
#关闭防火墙和selinux
service iptables stop
setenforce 0 >/dev/null 2>&1
sed -i '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config
#配置yum源(一般是内网源)
#test network
ping -c 1 $ipremote > /dev/null 2>&1
if [ $? -ne 0 ];then
echo "你的网络不通,请先检查你的网络"
exit 1
else
echo "网络ok."
fi
cat > /etc/yum.repos.d/server.repo << end
[server]
name=server
baseurl=ftp://$ipremote
enabled=1
gpgcheck=0
end
#安装软件
read -p "请输入需要安装的软件,多个用空格隔开:" soft
yum -y install $soft &>/dev/null
#备份配置文件
conf=/etc/vsftpd/vsftpd.conf
\cp $conf $conf.default
#根据需求修改配置文件
sed -ir '/^#|^$/d' $conf
sed -i '/local_enable/c\local_enable=NO' $conf
sed -i '$a anon_upload_enable=YES' $conf
sed -i '$a anon_mkdir_write_enable=YES' $conf
sed -i '$a anon_other_write_enable=YES' $conf
sed -i '$a anon_max_rate=512000' $conf
#启动服务
service vsftpd restart &>/dev/null && echo"vsftpd服务启动成功"
#测试验证
chmod 777 /var/ftp/pub
cp /etc/hosts /var/ftp/pub
#测试下载
cd /tmp
lftp $ipaddr <<end
cd pub
get hosts
exit
end
if [ -f /tmp/hosts ];then
echo "匿名用户下载成功"
rm -f /tmp/hosts
else
echo "匿名用户下载失败"
fi
#测试上传、创建目录、删除目录等
cd /tmp
lftp $ipaddr << end
cd pub
mkdir test1
mkdir test2
put /etc/group
rmdir test2
exit
end
if [ -d /var/ftp/pub/test1 ];then
echo "创建目录成功"
if [ ! -d /var/ftp/pub/test2 ];then
echo "文件删除成功"
fi
else
if [ -f /var/ftp/pub/group ];then
echo "文件上传成功"
else
echo "上传、创建目录删除目录部ok"
fi
fi
[ -f /var/ftp/pub/group ] && echo "上传文件成功"
awk
是一种编程语言,主要用于在linux/unix下对文本和数据进行处理,是linux/unix下的一个工具。数据可以来自标准输入、一个或多个文件,或其它命令的输出。
awk
的处理文本和数据的方式:逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。
awk
分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。
gawk
是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。
下面介绍的awk是以GNU的gawk
为例的,在linux系统中已把awk链接到gawk,所以下面全部以awk进行介绍。
awk能干啥:
awk用来处理文件和数据的,是类unix下的一个工具,也是一种编程语言
可以用来统计数据,比如网站的访问量,访问的IP量等等
支持条件判断,支持for和while循环
语法结构:
awk 选项 '命令部分' 文件名
特别说明:
引用shell变量需用双引号引起
常用选项:
-F
定义字段分割符号,默认的分隔符是空格-v
定义变量并赋值‘命名部分’ 说明:
'/root/{awk语句}' sed中: '/root/p'
'NR==1,NR==5{awk语句}' sed中: '1,5p'
'/^root/,/^ftp/{awk语句}' sed中:'/^root/,/^ftp/p'
{awk语句1; awk语句2;...}
'{print $0;print $1}' sed中:'p'
'NR==5{print $0}' sed中:'5p'
注:awk命令语句间用分号间隔
BEGIN...END....
'BEGIN{awk语句};{处理中};END{awk语句}'
'BEGIN{awk语句};{处理中}'
'{处理中};END{awk语句}'
awk -f awkScript.sh file
★★★)脚本编写:
#!/bin/awk -f 定义魔法字符
以下是awk引号里的命令清单,不要用引号保护命令,多个命令用分号间隔
BEGIN{FS=":"}
NR==1,NR==3{print $1"\t"$NF}
...
脚本执行:
方法1:
awk 选项 -f awk的脚本文件 要处理的文本文件
awk -f awk.sh filename
sed -f sed.sh -i filename
方法2:
./awk的脚本文件(或者绝对路径) 要处理的文本文件
./awk.sh filename
./sed.sh filename
变量 | 变量说明 | 备注 |
---|---|---|
$0 | 当前处理行的所有记录 | |
1,2,3...n | 文件中每行以间隔符号分割的不同字段 | awk -F: ‘{print 1,3}’ |
NF | 当前记录的字段数(列数) | awk -F: ‘{print NF}’ |
$NF | 最后一列 | $(NF-1)表示倒数第二列 |
FNR/NR | 行号 | |
FS | 定义间隔符 | ‘BEGIN{FS=“:”};{print 1,3}’ |
OFS | 定义输出字段分隔符,默认空格 | ‘BEGIN{OFS=“\t”};print 1,3}’ |
RS | 输入记录分割符,默认换行 | ‘BEGIN{RS=“\t”};{print $0}’ |
ORS | 输出记录分割符,默认换行 | ‘BEGIN{ORS=“\n\n”};{print 1,3}’ |
FILENAME | 当前输入的文件名 |
文件准备:
root:x:0:0:root:/roots:/bin/bash
bin:x:1:1:bin:/bins:/sbin/nologin
daemon123:x:2:2:daemon:/sbins:/sbin/nologin
adm:x:3:4:adm:/var/adms:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpds:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
awk -F: '{print $1,$(NF-1)}' sed_test.txt #使用":"分隔符对行进行切分
root /roots
bin /bins
daemon123 /sbins
adm /var/adms
lp /var/spool/lpds
298374837483 298374837483
172.16.0.254 172.16.0.254
10.1.1.1 10.1.1.1
awk -F: '{print $1,$(NF-1),$NF,NF}' sed_test.txt
root /roots /bin/bash 7
bin /bins /sbin/nologin 7
daemon123 /sbins /sbin/nologin 7
adm /var/adms /sbin/nologin 7
lp /var/spool/lpds /sbin/nologin 7
298374837483 298374837483 298374837483 1
172.16.0.254 172.16.0.254 172.16.0.254 1
10.1.1.1 10.1.1.1 10.1.1.1 1
awk '/root/{print $0}' 1.txt
# awk '/root/' 1.txt
# awk -F: '/root/{print $1,$NF}' 1.txt
root /bin/bash
# awk -F: '/root/{print $0}' 1.txt
root:x:0:0:root:/root:/bin/bash
# awk 'NR==1,NR==5' 1.txt
# awk 'NR==1,NR==5{print $0}' 1.txt
# awk 'NR==1,NR==5;/^root/{print $0}' 1.txt
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
FS和OFS:
awk 'BEGIN{FS=":"};/^root/,/^lp/{print $1,$NF}' 1.txt
awk -F: 'BEGIN{OFS="\t\t"};/^root/,/^lp/{print $1,$NF}' 1.txt
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
awk -F: 'BEGIN{OFS="@@@"};/^root/,/^lp/{print $1,$NF}' 1.txt
root@@@/bin/bash
bin@@@/sbin/nologin
daemon@@@/sbin/nologin
adm@@@/sbin/nologin
lp@@@/sbin/nologin
[root@server shell07]#
RS和ORS:
修改源文件前2行增加制表符和内容:
vim 1.txt
root:x:0:0:root:/root:/bin/bash hello world
bin:x:1:1:bin:/bin:/sbin/nologin test1 test2
# awk 'BEGIN{RS="\t"};{print $0}' 1.txt
# awk 'BEGIN{ORS="\t"};{print $0}' 1.txt
awk -F: '{print $1,$3}' /etc/passwd
awk
使用一行作为输入,并将这一行赋给内部变量$0
,每一行也可称为一个记录,以换行符(RS)结束
每行被间隔符:
(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1
开始
问:awk如何知道用空格来分隔字段的呢?
答:因为有一个内部变量FS来确定字段分隔符。初始时,FS赋为空格
awk
使用print
函数打印字段,打印出来的字段会以空格分隔,因为1,3之间有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格
awk
处理完一行后,将从文件中获取另一行,并将其存储在$0
中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕
print
和printf
Note:
%s 字符类型 strings %-20s
%d 数值类型
-
表示左对齐,默认是右对齐printf默认不会在行尾自动换行,加\n
print函数 类似echo "hello world"
# date |awk '{print "Month: "$2 "\nYear: "$NF}'
# awk -F: '{print "username is: " $1 "\t uid is: "$3}' /etc/passwd
printf函数 类似echo -n
# awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}' /etc/passwd
# awk -F: '{printf "|%15s| %10s| %15s|\n", $1,$2,$3}' /etc/passwd
# awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd
awk 'BEGIN{FS=":"};{printf "%-15s %-15s %-15s\n",$1,$6,$NF}' a.txt
Note:awk
中调用定义的变量不需要加$
awk -v NUM=3 -F: '{ print $NUM }' /etc/passwd
awk -v NUM=3 -F: '{ print NUM }' /etc/passwd
awk -v num=1 'BEGIN{print num}'
1
awk -v num=1 'BEGIN{print $num}'
BEGIN
:表示在程序开始前执行
END
:表示所有文件处理完后执行
用法:'BEGIN{开始处理之前};{处理中};END{处理结束后}'
,可以只存在'BEGIN{开始处理之前};{处理中};'
或者'{处理中};END{处理结束后}'
打印最后一列和倒数第二列(登录shell和家目录)
awk -F: 'BEGIN{ print "Login_shell\t\tLogin_home\n*******************"};{print $NF"\t\t"$(NF-1)};END{print "************************"}' 1.txt
awk 'BEGIN{ FS=":";print "Login_shell\tLogin_home\n*******************"};{print $NF"\t"$(NF-1)};END{print "************************"}' 1.txt
Login_shell Login_home
************************
/bin/bash /root
/sbin/nologin /bin
/sbin/nologin /sbin
/sbin/nologin /var/adm
/sbin/nologin /var/spool/lpd
/bin/bash /home/redhat
/bin/bash /home/user01
/sbin/nologin /var/named
/bin/bash /home/u01
/bin/bash /home/YUNWEI
************************************
打印/etc/passwd里的用户名、家目录及登录shell
u_name h_dir shell
***************************
***************************
awk -F: 'BEGIN{OFS="\t\t";print"u_name\t\th_dir\t\tshell\n***************************"};{printf "%-20s %-20s %-20s\n",$1,$(NF-1),$NF};END{print "****************************"}'
# awk -F: 'BEGIN{print "u_name\t\th_dir\t\tshell" RS "*****************"} {printf "%-15s %-20s %-20s\n",$1,$(NF-1),$NF}END{print "***************************"}' /etc/passwd
格式化输出:
echo print
echo -n printf
{printf "%-15s %-20s %-20s\n",$1,$(NF-1),$NF}
运算符 | 说明 |
---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
~ | 匹配 |
!~ | 不匹配 |
! | 逻辑非 |
&& | 逻辑与 |
\ | \ |
从第一行开始匹配到以lp开头行
awk -F: 'NR==1,/^lp/{print $0 }' passwd
从第一行到第5行
awk -F: 'NR==1,NR==5{print $0 }' passwd
从以lp开头的行匹配到第10行
awk -F: '/^lp/,NR==10{print $0 }' passwd
从以root开头的行匹配到以lp开头的行
awk -F: '/^root/,/^lp/{print $0}' passwd
打印以root开头或者以lp开头的行
awk -F: '/^root/ || /^lp/{print $0}' passwd
awk -F: '/^root/;/^lp/{print $0}' passwd
显示5-10行
awk -F':' 'NR>=5 && NR<=10 {print $0}' /etc/passwd
awk -F: 'NR<10 && NR>5 {print $0}' passwd
打印30-39行以bash结尾的内容:
[root@MissHou shell06]$ awk 'NR>=30 && NR<=39 && $0 ~ /bash$/{print $0}' passwd
stu1:x:500:500::/home/stu1:/bin/bash
yunwei:x:501:501::/home/yunwei:/bin/bash
user01:x:502:502::/home/user01:/bin/bash
user02:x:503:503::/home/user02:/bin/bash
user03:x:504:504::/home/user03:/bin/bash
[root@MissHou shell06]$ awk 'NR>=3 && NR<=8 && /bash$/' 1.txt
stu7:x:1007:1007::/rhome/stu7:/bin/bash
stu8:x:1008:1008::/rhome/stu8:/bin/bash
stu9:x:1009:1009::/rhome/stu9:/bin/bash
打印文件中1-5并且以root开头的行
[root@MissHou shell06]$ awk 'NR>=1 && NR<=5 && $0 ~ /^root/{print $0}' 1.txt
root:x:0:0:root:/root:/bin/bash
[root@MissHou shell06]$ awk 'NR>=1 && NR<=5 && $0 !~ /^root/{print $0}' 1.txt
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
理解;号和||的含义:
[root@MissHou shell06]$ awk 'NR>=3 && NR<=8 || /bash$/' 1.txt
[root@MissHou shell06]$ awk 'NR>=3 && NR<=8;/bash$/' 1.txt
打印IP地址
$ ifconfig eth0|awk 'NR>1 {print $2}'|awk -F':' 'NR<2 {print $2}'
$ ifconfig eth0|grep Bcast|awk -F':' '{print $2}'|awk '{print $1}'
$ ifconfig eth0|grep Bcast|awk '{print $2}'|awk -F: '{print $2}'
$ ifconfig eth0|awk NR==2|awk -F '[ :]+' '{print $4RS$6RS$8}'
$ ifconfig eth0|awk -F"[ :]+" '/inet addr:/{print $4}'
[root@MissHou ~] awk '/bash$/{print $0}' /etc/passwd
[root@MissHou ~] awk '/bash$/{print $0}' /etc/passwd
[root@MissHou ~] awk '/bash$/' /etc/passwd
[root@MissHou ~] awk -F: '$7 ~ /bash/' /etc/passwd
[root@MissHou ~] awk -F: '$NF ~ /bash/' /etc/passwd
[root@MissHou ~] awk -F: '$0 ~ /bash/' /etc/passwd
[root@MissHou ~] awk -F: '$0 ~ /\/bin\/bash/' /etc/passwd
$ awk -F: '$0 ~ /\/bin\/bash/{print $1}' /etc/passwd
500 stu1
501 yunwei
502 user01
503 user02
504 user03
$ awk -F: 'BEGIN{print "UID\tUSERNAME"} {if($3>=500 && $3 !=65534 ) {print $3"\t"$1} }' /etc/passwdUID USERNAME
$ awk -F: '{if($3 >= 500 && $3 != 65534) print $1,$3}' a.txt
redhat 508
user01 509
u01 510
YUNWEI 511
if语句:
if [ xxx ];then
xxx
fi
格式:
awk 选项 '正则,地址定位{awk语句}' 文件名
{ if(表达式){语句1;语句2;...}}
awk -F: '{if($3>=500 && $3<=60000) {print $1,$3} }' passwd
$ awk -F: '{if($3==0) {print $1"是管理员"} }' passwd
root是管理员
$ awk 'BEGIN{if('$(id -u)'==0) {print "admin"} }'
admin
if...else语句:
if [ xxx ];then
xxxxx
else
xxx
fi
格式:
{if(表达式){语句;语句;...}else{语句;语句;...}}
awk -F: '{ if($3>=500 && $3 != 65534) {print $1"是普通用户"} else {print $1,"不是普通用户"}}' passwd
awk 'BEGIN{if( '$(id -u)'>=500 && '$(id -u)' !=65534 ) {print "是普通用户"} else {print "不是普通用户"}}'
if [xxxx];then
xxxx
elif [xxx];then
xxx
....
else
...
fi
if...else if...else语句:
格式:
{ if(表达式1){语句;语句;...}else if(表达式2){语句;语句;...}else if(表达式3){语句;语句;...}else{语句;语句;...}}
awk -F: '{ if($3==0) {print $1,":是管理员"} else if($3>=1 && $3<=499 || $3==65534 ) {print $1,":是系统用户"} else {print $1,":是普通用户"}}'
awk -F: '{ if($3==0) {i++} else if($3>=1 && $3<=499 || $3==65534 ) {j++} else {k++}};END{print "管理员个数为:"i "\n系统用户个数为:"j"\n普通用户的个数为:"k }'
# awk -F: '{if($3==0) {print $1,"is admin"} else if($3>=1 && $3<=499 || $3==65534) {print $1,"is sys users"} else {print $1,"is general user"} }' a.txt
root is admin
bin is sys users
daemon is sys users
adm is sys users
lp is sys users
redhat is general user
user01 is general user
named is sys users
u01 is general user
YUNWEI is general user
awk -F: '{ if($3==0) {print $1":管理员"} else if($3>=1 && $3<500 || $3==65534 ) {print $1":是系统用户"} else {print $1":是普通用户"}}' /etc/passwd
awk -F: '{if($3==0) {i++} else if($3>=1 && $3<500 || $3==65534){j++} else {k++}};END{print "管理员个数为:" i RS "系统用户个数为:"j RS "普通用户的个数为:"k }' /etc/passwd
管理员个数为:1
系统用户个数为:28
普通用户的个数为:27
# awk -F: '{ if($3==0) {print $1":是管理员"} else if($3>=500 && $3!=65534) {print $1":是普通用户"} else {print $1":是系统用户"}}' passwd
awk -F: '{if($3==0){i++} else if($3>=500){k++} else{j++}} END{print i; print k; print j}' /etc/passwd
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理员个数: "i; print "普通用个数: "k; print "系统用户: "j}' /etc/passwd
如果是普通用户打印默认shell,如果是系统用户打印用户名
# awk -F: '{if($3>=1 && $3<500 || $3 == 65534) {print $1} else if($3>=500 && $3<=60000 ) {print $NF} }' /etc/passwd
打印1~5
for ((i=1;i<=5;i++));do echo $i;done
awk 'BEGIN { for(i=1;i<=5;i++) {print i} }'
打印1~10中的奇数
for ((i=1;i<=10;i+=2));do echo $i;done|awk '{sum+=$0};END{print sum}'
awk 'BEGIN{ for(i=1;i<=10;i+=2) {print i} }'
awk 'BEGIN{ for(i=1;i<=10;i+=2) print i }'
计算1-5的和
awk 'BEGIN{sum=0;for(i=1;i<=5;i++) sum+=i;print sum}'
awk 'BEGIN{for(i=1;i<=5;i++) (sum+=i);{print sum}}'
awk 'BEGIN{for(i=1;i<=5;i++) (sum+=i);print sum}'
打印1-5
i=1;while (($i<=5));do echo $i;let i++;done
awk 'BEGIN { i=1;while(i<=5) {print i;i++} }'
打印1~10中的奇数
awk 'BEGIN{i=1;while(i<=10) {print i;i+=2} }'
计算1-5的和
awk 'BEGIN{i=1;sum=0;while(i<=5) {sum+=i;i++}; print sum }'
awk 'BEGIN {i=1;while(i<=5) {(sum+=i) i++};print sum }'
嵌套循环:
#!/bin/bash
for ((y=1;y<=5;y++))
do
for ((x=1;x<=$y;x++))
do
echo -n $x
done
echo
done
awk 'BEGIN{ for(y=1;y<=5;y++) {for(x=1;x<=y;x++) {printf x} ;print } }'
awk 'BEGIN { for(y=1;y<=5;y++) { for(x=1;x<=y;x++) {printf x};print} }'
1
12
123
1234
12345
awk 'BEGIN{ y=1;while(y<=5) { for(x=1;x<=y;x++) {printf x};y++;print}}'
1
12
123
1234
12345
尝试用三种方法打印99口诀表:
awk 'BEGIN{for(y=1;y<=9;y++) { for(x=1;x<=y;x++) {printf x"*"y"="x*y"\t"};print} }'
awk 'BEGIN{for(y=1;y<=9;y++) { for(x=1;x<=y;x++) printf x"*"y"="x*y"\t";print} }'
awk 'BEGIN{i=1;while(i<=9){for(j=1;j<=i;j++) {printf j"*"i"="j*i"\t"};print;i++ }}'
awk 'BEGIN{for(i=1;i<=9;i++){j=1;while(j<=i) {printf j"*"i"="i*j"\t";j++};print}}'
循环的控制:
break 条件满足的时候中断循环
continue 条件满足的时候跳过循环
# awk 'BEGIN{for(i=1;i<=5;i++) {if(i==3) break;print i} }'
1
2
# awk 'BEGIN{for(i=1;i<=5;i++){if(i==3) continue;print i}}'
1
2
4
5
+ - * / %(模) ^(幂2^3)
可以在模式中执行计算,awk都将按浮点数方式执行算术运算
awk 'BEGIN{print 1+1}'
awk 'BEGIN{print 1**1}'
awk 'BEGIN{print 2**3}'
awk 'BEGIN{print 2/3}'
awk -F: '{ shells[$NF]++ };END{for (i in shells) {print i,shells[i]} }' /etc/passwd
books[linux]++
books[linux]=1
shells[/bin/bash]++
shells[/sbin/nologin]++
/bin/bash 5
/sbin/nologin 6
shells[/bin/bash]++ a
shells[/sbin/nologin]++ b
shells[/sbin/shutdown]++ c
books[linux]++
books[php]++
ss -antp|grep 80|awk '{states[$1]++};END{for(i in states){print i,states[i]}}'
TIME_WAIT 578
ESTABLISHED 1
LISTEN 1
ss -an |grep :80 |awk '{states[$2]++};END{for(i in states){print i,states[i]}}'
LISTEN 1
ESTAB 5
TIME-WAIT 25
ss -an |grep :80 |awk '{states[$2]++};END{for(i in states){print i,states[i]}}' |sort -k2 -rn
TIME-WAIT 18
ESTAB 8
LISTEN 1
netstat -ant |grep :80 |awk -F: '{ip_count[$8]++};END{for(i in ip_count){print i,ip_count[i]} }' |sort
ss -an |grep :80 |awk -F":" '!/LISTEN/{ip_count[$(NF-1)]++};END{for(i in ip_count){print i,ip_count[i]}}' |sort -k2 -rn |head
统计Apache/Nginx日志中某一天的PV量 <统计日志>
grep '27/Jul/2017' mysqladmin.cc-access_log |wc -l
14519
统计Apache/Nginx日志中某一天不同IP的访问量 <统计日志>
grep '27/Jul/2017' mysqladmin.cc-access_log |awk '{ips[$1]++};END{for(i in ips){print i,ips[i]} }' |sort -k2 -rn |head
grep '07/Aug/2017' access.log |awk '{ips[$1]++};END{for(i in ips){print i,ips[i]} }' |awk '$2>100' |sort -k2 -rn
名词解释:
网站浏览量(PV) 名词:PV=PageView (网站浏览量) 说明:指页面的浏览次数,用以衡量网站用户访问的网页数量。多次打开同一页面则浏览量累计。用户每打开一个页面便记录1次PV。
名词:VV = Visit View(访问次数) 说明:从访客来到您网站到最终关闭网站的所有页面离开,计为1次访问。若访客连续30分钟没有新开和刷新页面,或者访客关闭了浏览器,则被计算为本次访问结束。
独立访客(UV) 名词:UV= Unique Visitor(独立访客数) 说明:1天内相同的访客多次访问您的网站只计算1个UV。
独立IP(IP) 名词:IP=独立IP数 说明:指1天内使用不同IP地址的用户访问网站的数量。同一IP无论访问了几个页面,独立IP数均为1
web服务器集群中总共有9台机器,上面部署的是Apache服务。由于业务不断增长,每天每台机器上都会产生大量的访问日志,现需要将每台web服务器上的apache访问日志保留最近3天的,3天以前的日志转储到一台专门的日志服务器上,已做后续分析。如何实现每台服务器上只保留3天以内的日志?
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 20:30:22- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |