# 行编辑器

vi/vim 称为全文本编辑器,sed 和 awk 称为行编辑器

  • 交互式和非交互式
  • 文件操作模式和行操作模式

# 一、sed

# 1. sed 的基本工作方式:
  • 将文件以行为单位读取到内存中
  • 使用 sed 的每个命令对该行进行操作
  • 处理完成后输出该行
# 2. 替换命令 s
sed 's/old/new/' filepath
sed -e 's/old/new/' -e 's/old/new/' filepath # 多条指令使用参数 - e
sed -i 's/old/new' filepath # 将替换的结果写回到原文件使用 - i
sed 's/正则表达式/new/' filepath # 使用正则表达式使用
sed -r 's/扩展正则表达式/new/' filepath # 使用扩展正则表达式使用 - r

案例

# 准备一个实验文件
head -5 /etc/passwd > afile
sed 's/root/chendong/' afile
sed 's:/:~:' afile # 可以使用其他符号代替 / 做命令的分隔符
sed -e 's/x/aa/' -e 's/aa/bb/' afile
# 上面命令可以简写为
sed 's/x/aa/;s/aa/bb/' afile
sed -i 's/x/bb/' afile
sed 's/..//' afile #可以使用元字符,不写替换内容即为空
sed 's/s*bin//' afile
sed -r 's/s+bin//' afile
sed 's/^root//' afile
# 3. 替换命令的更多选项
  • 全局替换
sed 's/old/new/g' filepath # 用于替换所有出现的地方
# 案例
sed 's/root/!!!!/g' afile
sed 's/root/!!!!/2' afile # 替换匹配到的第 2 次
  • 寻址
sed '/正则表达式/s/old/new/g' filepath # 匹配了正则表达式的行才执行替换
sed '行号s/old/new/g' filepath # 指定行号
sed '行号1,行号2s/old/new/g' filepath # 指定从行号 1 到行号 2 的行
# 案例
sed '1,3s/adm/!!!!/g' afile
sed '1,$s/adm/!!!!/g' afile # 指定从第 1 行到最后一行
sed '/^root/s/bash/!!!/' afile # 通过正则表达式匹配 root 开头的行
# 4. 其他命令
  • 删除
    • d 命令后的其他命令不会被执行
    • 不会更改原文件
sed '[寻址]d' filepath 
# 案例
sed '/root/d' afile # 匹配到 root 行都删除
  • 追加、插入、更改
sed '/root/a hello' afile # a 在匹配的行的下一行插入指定内容
sed '/root/i hello' afile # i 在匹配的行的上一行插入指定内容
sed '/root/c hello' afile # c 将匹配的行更改为指定内容
#

# 二、awk

# 1. awk 流程控制
  • 输入数据前 BEGIN {}
  • 主输入循环 {}
  • 所有文件读取完成 END {}
  • 不需要写所有流程
# 2. awk 的字段
  • 每行称为 awk 的记录
  • 使用空格、制表符分隔开的单词称作字段
  • 可以自己指定分隔的字段
awk '{print $1, $2, $3}' filepath # $1, $2, $3 ... $n 表示每一个字段 \t
awk -F ':' '{print $1, $2, $3}' filepath # 使用 - F 选项可以改变字段分隔符

案例:

awk -F "'" '/^menu/{ print $2 }' /boot/grub2/grub.cfg
awk -F "'" '/^menu/{ print x++,$2 }' /boot/grub2/grub.cfg # 输出行号
# 3. awk 表达式
  • 赋值操作符
var1 = "name"
var2 = "hello" "world" # 字符串连接
var3 = $1 # 第一个字段
  • 算数操作符
+ - * / % ^
  • 系统变量
    • FS 字段分隔符,OFS 输出字段分隔符
    • RS 记录分隔符
    • NR 行数
    • NF 字段数量,最后一个字段内容可以使用 NF 取出
awk 'BEGIN{FS=":"}{print $1}' afile # 等同于 awk -F ":" '{print $1}' afile
awk 'BEGIN{RS=":"}{print $0}' afile
awk '{print NR, $0}' afile 
awk '{print NF}' afile
  • 关系操作符
< > <= >= == != 
# 匹配字符、不匹配字符
~ !~
  • 布尔操作符
&& || !
# 4. 判断和循环
  • 条件语句
if(表达式) {
  awk语句
}
else {
  awk语句2
}

案例:

# 准备实验文件 scores.txt
user1 80 90 67
user2 60 67 90
user3 82 87 83
user4 100 75 68
awk '{if($2>=80) print $1}' scores.txt
awk '{if($2>=80) {print $1; print $2}}' scores.txt
  • 循环语句

sum=0 ; for(i=2;i<=NF;i++) sum+=$i ; print sum

while(表达式) {
  awk语句
}
do {
  awk语句
}while(表达式)
  
for(初始值;循环判断条件;累加) {
  awk语句
}
  • 同样也支持 break,continue

案例:

awk '{sum=0 ; for(i=2;i<=NF;i++) sum+=$i ; print sum, sum/(NF-1) }' scores.txt
# 5. awk 数组
  • 数组的定义
    • 下标可以使用字符串
  • 数组的遍历
awk '{sum=0 ; for(i=2;i<=NF;i++) sum+=$i ; avg[$1]=sum/(NF-1) }END{for(user in avg) sum2+=avg[user]; print sum2/NR}' scores.txt
sum=0 
for(i=2;i<=NF;i++) 
sum+=$i
avg[$1]=sum/(NF-1)
for(user in avg) 
sum2+=avg[user]
print sum2/NR
更新于

请我喝[茶]~( ̄▽ ̄)~*

YunBao 微信支付

微信支付

YunBao 支付宝

支付宝

YunBao 贝宝

贝宝