当前位置: 首页 > news >正文

day020-sed和find

文章目录

  • 1. sed
    • 1.1 查找、过滤文本
      • 1.1.1 根据行号取行
      • 1.1.2 根据行号取范围
      • 1.1.3 过滤出指定行
      • 1.1.4 过滤出指定范围内容
    • 1.2 替换文件内容
      • 1.2.1 将文件中虚拟用户命令解释器替换成/bin/bash
      • 1.2.2 修改原文件并备份
      • 1.2.3 为每行开头加上#
    • 1.3 反向引用(后向引用)
      • 1.3.1 将用户名和命令解释器调换位置
      • 1.3.2 将日志中时间格式改为年月日
    • 1.4 删除
      • 1.4.1 按照行号删除
      • 1.4.2 将空行或以#开头的行删除
    • 1.5 增加数据
      • 1.5.1 a
      • 1.5.2 i
      • 1.5.3 c
    • 1.6 案例:排除/删除sshd配置文件中的空行或注释行(不需要真的删除)
  • 2. find
    • 2.1 find基础使用
      • 2.1.1 找出/etc下以.conf结尾的文件
      • 2.1.2 找出/etc下大于100k的文件
      • 2.1.3 找出/var/log目录下以.log结尾7天前的文件
    • 2.2 find进阶使用
      • 2.2.1 在/etc下找出以.conf结尾的文件,找出这些文件中包含root或oldboy的行
      • 2.2.2 在/etc下找出以.conf结尾的文件,将这些文件打包
      • 2.2.3 找出/var/log目录下以.log结尾的文件复制到/backup/logs目录
  • 3. 踩坑记录
    • 3.1 find: 遗漏“-exec”的参数
  • 4. 思维导图

1. sed

sed格式:

sed 选项 脚本 文件

  • sed(Stream Editor)是 Linux/Unix 下的流式文本编辑器,用于对文本进行查找、替换、删除、插入等操作,支持正则表达式。
  • sed“流式编辑”(Stream Editing)特性体现在它处理文本的方式上:逐行读取、即时处理、无需加载整个文件到内存
  • grepawk 在处理文本时,默认也是逐行读取数据(流式处理)

1.1 查找、过滤文本

  • sed默认是自动打印模式,从输入(stdin或文件)逐行读取数据,并输出原文件数据。
  • -n:取消自动打印模式

1.1.1 根据行号取行

  • 脚本选项p:print,将结果输出
[root@oldboy99-Kylin ~/oldboy]# sed -n '1p' passwd
root:x:0:0:root:/root:/bin/bash

1.1.2 根据行号取范围

[root@oldboy99-Kylin ~/oldboy]# sed -n '1,5p' 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
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

1.1.3 过滤出指定行

  • -r:使用扩展正则表达式
  • 过滤出包含root或oldboy的行
[root@oldboy99-Kylin ~/oldboy]# sed -rn '/root|oldboy/p' passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
oldboy:x:1000:1000::/home/oldboy:/bin/bash

1.1.4 过滤出指定范围内容

  • 按时间范围过滤出日志内容
[root@oldboy99-Kylin ~/oldboy]# sed -n '/11:05:00/,/11:06:00/p' access.log |head -n 1
114.84.238.226 - - [22/Nov/2015:11:05:00 +0800] "GET /online/oldboyonline/order/mapInfoWindow.css HTTP/1.1" 200 608 "http://www.papaonline.com.cn/online/oldboyonline/order/orderNow.jsp" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36"
[root@oldboy99-Kylin ~/oldboy]# sed -n '/11:05:00/,/11:06:00/p' access.log |wc -l
3366
  • 取出日志中从第一行到11:30范围的日志,并取出第一列,统计最多的ip,取前五名
[root@oldboy99-Kylin ~/oldboy]# sed -n '1,/11:30:00/p' access.log |awk '{print $1}' |sort |uniq -c |sort -k1nr |head -55883 112.64.171.985574 58.220.223.62957 116.216.0.60799 114.83.184.139792 121.235.250.231
# 用awk过滤
[root@oldboy99-Kylin ~/oldboy]# awk 'NR==1,/11:30:00/{print $1}' access.log |sort |uniq -c |sort -k1nr |head -55883 112.64.171.985574 58.220.223.62957 116.216.0.60799 114.83.184.139792 121.235.250.231

1.2 替换文件内容

  • 脚本选择:s###g
  • s:substitute,替换
  • g:global,整行替换
  • 中间的分隔符可以换成其他的符号:@、/等

1.2.1 将文件中虚拟用户命令解释器替换成/bin/bash

  • 基础替换不会改变文件内容
  • 替换操作时需要查看输出结果,所以不要加-n;也不需要指定输出,不要加p
[root@oldboy99-Kylin ~/oldboy]# sed  's#/sbin/nologin#/bin/bash/#g' passwd |head -5
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/bash/
daemon:x:2:2:daemon:/sbin:/bin/bash/
adm:x:3:4:adm:/var/adm:/bin/bash/
lp:x:4:7:lp:/var/spool/lpd:/bin/bash/
  • -i:in-place,直接修改文件内容
[root@oldboy99-Kylin ~/oldboy]# sed -i 's#/sbin/nologin#/bin/bash/#g' passwd 
[root@oldboy99-Kylin ~/oldboy]# head -n 5 passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/bash/
daemon:x:2:2:daemon:/sbin:/bin/bash/
adm:x:3:4:adm:/var/adm:/bin/bash/
lp:x:4:7:lp:/var/spool/lpd:/bin/bash/
[root@oldboy99-Kylin ~/oldboy]# grep '/sbin/nologin' passwd
[root@oldboy99-Kylin ~/oldboy]# 

1.2.2 修改原文件并备份

  • -i[扩展名]:直接修改文件(如果指定扩展名则备份文件)
[root@oldboy99-Kylin ~/oldboy]# ll
-rw-r--r-- 1 root root     2006  526 14:33 passwd
[root@oldboy99-Kylin ~/oldboy]# sed -i.bak 's#/sbin/nologin#/bin/bash#g' passwd 
[root@oldboy99-Kylin ~/oldboy]# ll
-rw-r--r-- 1 root root     1874  526 14:34 passwd
-rw-r--r-- 1 root root     2006  526 14:33 passwd.bak
[root@oldboy99-Kylin ~/oldboy]# grep '/sbin/nologin' passwd
[root@oldboy99-Kylin ~/oldboy]# 

1.2.3 为每行开头加上#

[root@oldboy99-Kylin ~/oldboy]# sed 's@^@#@g' passwd
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/bin/bash
#daemon:x:2:2:daemon:/sbin:/bin/bash
#adm:x:3:4:adm:/var/adm:/bin/bash
……

1.3 反向引用(后向引用)

  • 通过正则表达式把要处理的内容进行分组,在后面通过数字引用进行处理

1.3.1 将用户名和命令解释器调换位置

[root@oldboy99-Kylin ~/oldboy]# sed -r 's#^(.+)(:x:.+:)(/.+)$#\3\2\1#g' passwd |head -5
/bin/bash:x:0:0:root:/root:root
/sbin/nologin:x:1:1:bin:/bin:bin
/sbin/nologin:x:2:2:daemon:/sbin:daemon
/sbin/nologin:x:3:4:adm:/var/adm:adm
/sbin/nologin:x:4:7:lp:/var/spool/lpd:lp

1.3.2 将日志中时间格式改为年月日

  • 过滤[]时要加反斜线
[root@oldboy99-Kylin ~/oldboy]# head -1 access.log 
101.226.61.184 - - [22/Nov/2015:11:02:00 +0800] "GET /mobile/sea-modules/gallery/zepto/1.1.3/zepto.js HTTP/1.1" 200 24662 "http://m.oldboyedu.com.cn/mobile/theme/oldboy/home/index.html" "Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; HUAWEI CRR-UL00 Build/HUAWEICRR-UL00) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025478 Mobile Safari/533.1 MicroMessenger/6.3.7.51_rbb7fa12.660 NetType/3gnet Language/zh_CN"
[root@oldboy99-Kylin ~/oldboy]# sed -r 's#^(.+\[)([0-9]+)/([A-Z][a-z]+/)(2015)(:.+)$#\1\4/\3\2\5#g' access.log |head -1
101.226.61.184 - - [2015/Nov/22:11:02:00 +0800] "GET /mobile/sea-modules/gallery/zepto/1.1.3/zepto.js HTTP/1.1" 200 24662 "http://m.oldboyedu.com.cn/mobile/theme/oldboy/home/index.html" "Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; HUAWEI CRR-UL00 Build/HUAWEICRR-UL00) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025478 Mobile Safari/533.1 MicroMessenger/6.3.7.51_rbb7fa12.660 NetType/3gnet Language/zh_CN"

1.4 删除

1.4.1 按照行号删除

  • 脚本参数d:删除
  • 不会影响原文件
[root@oldboy99-Kylin ~/oldboy]# sed '1d' passwd 
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
……
# 按照行号范围删除
[root@oldboy99-Kylin ~/oldboy]# sed '1,5d' passwd 
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
……

1.4.2 将空行或以#开头的行删除

[root@oldboy99-Kylin ~/oldboy]# sed -r '/^$|^#/d' 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
……

1.5 增加数据

脚本参数说明
aappend,在指定的行后面追加一行
iinsert,在指定的行上面追加一行
creplace,把指定的行内容替换掉

1.5.1 a

[root@oldboy99-Kylin ~/oldboy]# sed '1a 孙克旭' passwd 
root:x:0:0:root:/root:/bin/bash
孙克旭
bin:x:1:1:bin:/bin:/sbin/nologin
……

1.5.2 i

[root@oldboy99-Kylin ~/oldboy]# sed '1i 孙克旭' passwd 
孙克旭
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
……

1.5.3 c

[root@oldboy99-Kylin ~/oldboy]# sed '1c 孙克旭' passwd 
孙克旭
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
……

1.6 案例:排除/删除sshd配置文件中的空行或注释行(不需要真的删除)

  • grep:
[root@oldboy99-Kylin ~]# grep -Ev '^$|^#' /etc/ssh/sshd_config
Port 12345
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
……
  • sed:
  • !:取反,注意符号的位置
[root@oldboy99-Kylin ~]# sed -rn '/^$|^#/!p' /etc/ssh/sshd_config
Port 12345
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
……
############################################
[root@oldboy99-Kylin ~]# sed -r '/^$|^#/d' /etc/ssh/sshd_config
Port 12345
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
……
  • awk:
[root@oldboy99-Kylin ~]# awk '!/^$|^#/' /etc/ssh/sshd_config
Port 12345
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
……

2. find

  • 根据指定的目录查找内容(文件、目录)
选项说明
-typef:文件
d:目录
-name文件名
-size文件大小,单位k(小写)、M(大写)、G(大写)
-mtime文件创建时间,+7:7天以前

2.1 find基础使用

2.1.1 找出/etc下以.conf结尾的文件

[root@oldboy99-Kylin ~]# find /etc/ -type f -name '*.conf'
/etc/resolv.conf
/etc/dnf/protected.d/systemd.conf
/etc/dnf/protected.d/sudo.conf
/etc/dnf/protected.d/dnf.conf
……

2.1.2 找出/etc下大于100k的文件

[root@oldboy99-Kylin ~]# find /etc/ -type f -size +100k
/etc/pki/ca-trust/extracted/edk2/cacerts.bin
/etc/pki/ca-trust/extracted/java/cacerts
……

2.1.3 找出/var/log目录下以.log结尾7天前的文件

[root@oldboy99-Kylin ~]# find /var/log/ -type f -name '*.log' -mtime +7
/var/log/dracut.log
/var/log/.kylin-post-actions-nochroot.log
/var/log/anaconda/anaconda.log
……

2.2 find进阶使用

2.2.1 在/etc下找出以.conf结尾的文件,找出这些文件中包含root或oldboy的行

  • 是文件内容中包含……,不是文件名
  • 管道的作用是将左侧的命令结果作为右侧的命令输入
  • 这里需要将文件路径作为grep的参数,而不是数据输入,所以使用xargs将左侧结果按行转换成右侧命令的参数
  • grep 的颜色输出在通过管道或 xargs 时会默认被禁用
[root@oldboy99-Kylin ~]# find /etc/ -type f -name '*.conf' |xargs grep -E 'root|oldboy' --color=auto
/etc/libreport/events.d/bugzilla_anaconda_event.conf:			sed 's/^.*rootpw.*$/<auto-removed line containing rootpw>/' -i $sf
/etc/libreport/events.d/collect_dnf.conf:            if [[ $username != "root" ]]; then
/etc/libreport/events.d/abrt_event.conf:# Example: if you want all users (not just root) to be able to see some problems:
/etc/libreport/events.d/smart_event.conf:# Access to /dev/sda usually requires root.
……

[root@oldboy99-Kylin ~]# grep -E 'root|oldboy' `find /etc/ -type f -name '*.conf'`
/etc/libreport/events.d/bugzilla_anaconda_event.conf:			sed 's/^.*rootpw.*$/<auto-removed line containing rootpw>/' -i $sf
/etc/libreport/events.d/collect_dnf.conf:            if [[ $username != "root" ]]; then
/etc/libreport/events.d/abrt_event.conf:# Example: if you want all users (not just root) to be able to see some problems:
/etc/libreport/events.d/smart_event.conf:# Access to /dev/sda usually requires root.
……

[root@oldboy99-Kylin ~]# find /etc/ -type f -name '*.conf' -exec grep -E --color=auto 'root|oldboy' {}  \; sed 's/^.*rootpw.*$/<auto-removed line containing rootpw>/' -i $sfif [[ $username != "root" ]]; then
# Example: if you want all users (not just root) to be able to see some problems:
# Access to /dev/sda usually requires root.
# Therefore we run it as post-create event, thus: under root.# Can't do it as analyzer step, non-root can't read log.
rootpw
……
  • -exec的方式显示的结果不明显

2.2.2 在/etc下找出以.conf结尾的文件,将这些文件打包

[root@oldboy99-Kylin ~]# find /etc/ -type f -name '*.conf' |xargs tar zcf /backup/etc-conf.tar.gz 
tar: 从成员名中删除开头的“/”
tar: 从硬连接目标中删除开头的“/”

[root@oldboy99-Kylin ~]# tar zcf /backup/etc-conf.tar.gz `find /etc/ -type f -name '*.conf'`
tar: 从成员名中删除开头的“/”
tar: 从硬连接目标中删除开头的“/”

# 错误方法:
[root@oldboy99-Kylin ~]# find /etc/ -type f -name '*.conf' -exec tar zcf /backup/etc-conf.tar.gz {} \;
tar: 从成员名中删除开头的“/”
tar: 从成员名中删除开头的“/”
tar: 从成员名中删除开头的“/”
……
[root@oldboy99-Kylin /backup]# tar tf etc-conf.tar.gz 
etc/pulse/daemon.conf
  • find的结果会进入{}内;
  • 如果有10个文件,tar命令执行了10次,而且每次都会覆盖原压缩包,所以最后的压缩包只有一个文件

[root@oldboy99-Kylin ~]# find /etc/ -type f -name '*.conf' -exec tar zcf /backup/etc-conf.tar.gz {} +
tar: 从成员名中删除开头的“/”
tar: 从硬连接目标中删除开头的“/”
  • +:批量处理模式
    会让 find 将匹配到的所有文件一次性传递给后面的命令

2.2.3 找出/var/log目录下以.log结尾的文件复制到/backup/logs目录

  • 问题和上面的tar一样,是参数位置问题
  • -t:后面指定目标目录;将源文件复制到该目录中
[root@oldboy99-Kylin ~]# find /var/log/ -type f -name '*.log' |xargs cp -t /backup/logs/
cp: 不会以'/var/log/dnf.librepo.log' 覆盖刚创建的'/backup/logs/dnf.librepo.log'
cp: 不会以'/var/log/hawkey.log' 覆盖刚创建的'/backup/logs/hawkey.log'

[root@oldboy99-Kylin ~]# yes |cp `find /var/log/ -type f -name '*.log'` /backup/logs/ 
cp:是否覆盖'/backup/logs/sssd_implicit_files.log'? 
cp:是否覆盖'/backup/logs/sssd.log'? 
cp:是否覆盖'/backup/logs/sssd_nss.log'
  • yes:自动对所有的询问回答yes
  • 或者不使用别名cp:\cp

find /var/log/ -type f -name '*.log' -exec cp {} /backup/logs/ \;

3. 踩坑记录

3.1 find: 遗漏“-exec”的参数

[root@oldboy99-Kylin ~]# find /var/log/ -type f -name '*.log' -exec cp {} /backup/logs/ +
find: 遗漏“-exec”的参数
  • -exec+ 参数必须直接放在 {} 后面

4. 思维导图

【金山文档】 思维导图 https://www.kdocs.cn/l/co3I7PtpTYQX

相关文章:

  • Python面试1
  • 【修电脑的小记录】打不开某个网站
  • 【备战秋招】C++音视频开发经典面试题整理
  • JAVA面试复习知识点
  • Flutter图片Image、本地图片、程程图片、圆片剪切、圆形图片
  • ceph 剔除 osd
  • 物流配送优化实战:用遗传算法破解选址难题
  • TMS320F28388使用sysconfig配置SCI通信(RS485+FIFO+Modbus)
  • Python训练营打卡 Day37
  • 行为型:责任链模式
  • 认知无线电系统中采用能量检测频谱感知
  • pytorch简单线性回归模型
  • 黑马点评--缓存更新策略及案例实现
  • ubuntu脚本常用命令
  • Halcon 图像预处理②
  • AI时代新词-数字孪生(Digital Twin)
  • 并发的产生及对应的解决方案之服务架构说明
  • 大模型Agent
  • [开源项目] 一款功能强大的超高音质音乐播放器
  • 无网络docker镜像迁移
  • 做网站推广选哪家/百度官方版
  • 设置网站关键词/拉新任务接单放单平台
  • 舞钢市做网站开发的公司/百度营销
  • 专业网站制作团队专业网站制作团队/百搜网络科技有限公司
  • 游戏介绍网站模板下载/百度搜图入口
  • 助孕网站优化推广/专业seo推广