目录
[-f script.sed](#-f script.sed)
[-l N](#-l N)
['n' 标志](#'n' 标志)
['I' 标志](#'I' 标志)
['w FILE' 标志](#'w FILE' 标志)
['d'](#'d')
['a text'](#'a text')
['i text'](#'i text')
['c text'](#'c text')
['h / H'](#'h / H')
['g / G'](#'g / G')
['T '(GNU)](#'T '(GNU))
[-v FS=','](#-v FS=',')
[-v RS='\n\n'](#-v RS='\n\n')
[-v OFS=','](#-v OFS=',')
[-v ORS='\t'](#-v ORS='\t')
[-f script.awk](#-f script.awk)
[NF](#NF)
[0](#0)
[ARGC / ARGV](#ARGC / ARGV)
[预处理 / 后处理](#预处理 / 后处理)
[BEGIN {}](#BEGIN {})
[END {}](#END {})
[数值 / 日期函数](#数值 / 日期函数)
[delete arr[i]](#delete arr[i])
[in 运算符](#in 运算符)
[exit [code]](#exit [code])
[? :](#? :)
前言
- 上篇介绍了Linux命令技术笔记-find+grep命令详解,本文介绍sed与awk高频选项及示例。
sed
- 功能 :流式文本编辑器,用于对文本进行替换、删除、插入等操作
- 基本语法格式 :sed [选项] '命令' 文件
基础选项
-i
-
就地修改
-
示例
cp /etc/passwd test1 #准备测试文件
echo root > patterns.txt
echo command >> patterns.txt
sed -i 's/root/ROOT/g' patterns.txt #直接替换文件中的 root → ROOT 并保存cat patterns.txt
ROOT
command
-i.bak
-
备份后修改
-
示例
sed -i.bak 's/ROOT/root/g' patterns.txt #先创建 patterns.txt.bak,再替换原文件
cat patterns.txt
root
commandcat patterns.txt.bak
ROOT
command
-i''(BSD)
-
就地修改(BSD/macOS)
-
示例
sed -i'' 's/root/new/g' patterns.txt #BSD/macOS 下实现就地修改
cat patterns.txt
new
command
-f script.sed
-
从文件读取脚本
-
示例
echo 's/root/ROOT/' > script.sed #创建测试脚本文件
echo '/root/a test' >> script.sed
sed -f script.sed test1 #批量执行 script.sed 中的多条 sed 命令
ROOT:x:0:0:root:/root:/bin/bash
test
bin:x:1:1:bin:/bin:/sbin/nologin
-e
-
多脚本顺序
-
示例
sed -e 's/root/ROOT/' -e 's/root/RooT/' test1 #顺序执行多条替换
ROOT:x:0:0:RooT:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
-n
-
静默输出
-
示例
sed ' ' test1 #默认全部输出
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologinsed -n ' ' test1 #无输出
-s
-
多文件独立处理
-
示例
sed -s 's/root/ROOT/' patterns.txt test1 #不把多个文件内容拼接,保持文件名独立
ROOT
command
ROOT:x:0:0:root:/root:/bin/bash
-u
-
无缓冲输出
-
示例
sed -u 's/root/ROOT/' test1 #实时输出每行替换结果,适合大文件
ROOT:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
-z
-
NUL 分隔符
-
示例
echo -e "This is the first line.\nold text here.\nAnother line with old.\nold" > test.txt #创建测试文件
sed -z 's/old/new/g' test.txt #正确处理含空格/换行的文件名
This is the first line.
new text here.
Another line with new.
new
正则/兼容
-r
-
扩展正则(GNU)
-
示例
sed -nr '/ro+/p' test1 #支持 + ? | 等扩展正则
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
chrony:x:996:993::/var/lib/chrony:/sbin/nologin
-E
-
扩展正则(BSD)
-
示例
sed -E 's/[0-9]+/num/g' file.txt #BSD/macOS 下支持扩展正则
Version num.num.num
Release num
ID: num
--posix
-
关闭 GNU 扩展
-
示例
echo -e "Version 1.2.3\nRelease 456\nID: 789" > file.txt #编写测试文件
sed --posix 's/[0-9]/num/g' file.txt #仅使用 POSIX 基本正则,避免 GNU 特有行为
Version num.num.num
Release numnumnum
ID: numnumnum
-b
-
二进制模式(GNU)
-
示例
echo -e "Line1\r\nLine2\r\nLine3" > dos.txt #创建测试文件
sed -b 's/\x0D//g' dos.txt #不转换换行符,直接处理 CR/LF,每行末尾的 \r 被删除,仅保留 \n
Line1
Line2
Line3
-l N
-
换行宽度(GNU)
-
示例
sed -l 64 's/$/\n/' test1 #每 64 字符后强制换行
root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
替换
's/pat/repl/flags'
-
替换
-
示例
sed 's/ro/RO/' test1
#把匹配到 ro 行的第一个ro 替换为 RO 并输出到 STDOUT
#可以将 / 换成符号来作为分隔符
ROot:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
'n' 标志
-
仅替换第 n 次匹配
-
示例
sed 's/root/ROOT/2' test1 #每行仅替换第 2 次出现的 root
root:x:0:0:ROOT:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
'g'
-
全局替换
-
示例
sed 's/ro/RO/g' test1 # #全局的将 ro 替换为 RO 并输出到 STDOUT
ROot:x:0:0:ROot:/ROot:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
'I' 标志
-
忽略大小写(GNU)
-
示例
sed 's/ROOT/RooT/I' test1 #行内所有 ROOT → RooT
RooT:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
'w FILE' 标志
-
写入新文件
-
示例
sed 's/root/ROOT/w new.txt' test1 #把替换后的行保存到 new.txt
cat new.txt
ROOT:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/ROOT:/sbin/nologin
'y/src/dst/'
-
字符映射
-
示例
sed 'y/root/RTSU/' test1 #把 r→R, o→T, t→U(逐字符替换)
RTTU:x:0:0:RTTU:/RTTU:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nTlTgin
daemTn:x:2:2:daemTn:/sbin:/sbin/nTlTgin
'&'
-
引用匹配
-
示例
sed 's/root/(R&O)/g' test1 #把 root 替换为 (RrootO)
(RrootO):x:0:0:(RrootO):/(RrootO):/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
删除
'd'
-
删除行
-
示例
sed '/^#/d' /etc/login.defs #删除所有以 # 开头的行,输出去注释后的内容
MAIL_DIR /var/spool/mail
UMASK 022
'1,3d'
-
删除范围
-
示例
sed '1,3d' test1 #仅删除1到3行的内容
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
'$d'
-
删除最后一行
-
示例
sed '$d' test1 #删除最后一行并输出其余内容
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!d'
-
保留首行
-
示例
sed '1!d' test1 #删除除第一行外的所有行
root:x:0:0:root:/root:/bin/bash
打印行
'p'
-
打印行
-
示例
sed -n '3,5p' test1 #仅打印 3 到 5 行
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
插入/追加/替换行
'a text'
-
行后追加
-
示例
sed '/root/a test' test1 #在匹配到 root 的行后追加 test 行
root:x:0:0:root:/root:/bin/bash
test
bin:x:1:1:bin:/bin:/sbin/nologin
'i text'
-
行前插入
-
示例
sed '/root/i test' test1 #在匹配到 root 的行前插入 test 行
test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
'c text'
-
整行替换
-
示例
sed '/root/c test' test1 #将匹配到 root 行的整行内容替换为 test
test
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
行号/流程
'='
-
输出行号
-
示例
sed '/root/=' test1 #输出匹配到 root 的行的行号
1
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
'q'
-
立即退出
-
示例
sed '2q' test1 #输出前 2 行后停止
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
'Q'(GNU)
-
立即退出(GNU,不输出当前行)
-
示例
sed '/sbin/Q' test1 #遇到 sbin 行立即退出,不再继续
root:x:0:0:root:/root:/bin/bash
模式空间操作
'N'
-
读入下一行合并
-
示例
sed 'N;s/\n/ /' patterns.txt #将文件中的连续两行合并为一行,并用空格替换换行符
new command
'D'
-
删除模式空间第一行
-
示例
sed 'N;D' patterns.txt #输出文件的最后一行
command
'P'
-
打印模式空间第一行
-
示例
sed -n '=;N;P;' test1 #输出文件中的所有奇数行
1
root:x:0:0:root:/root:/bin/bash
3
daemon:x:2:2:daemon:/sbin:/sbin/nologin
5
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
保持空间
'h / H'
-
复制/追加到保持空间
-
示例
sed '1h;2,$G' patterns.txt #将文件的第一行复制到每一行末尾
new
command
newsed '1H;2,$G' patterns.txt #将第一行内容追加到每一行末尾
new
commandnew
'g / G'
-
从保持空间取回/追加
-
示例
sed '1h;2,$g' test1 #用第一行内容替换所有后续行
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
'x'
-
交换模式空间与保持空间
-
示例
sed '/new/x' patterns.txt #当匹配到 start 时,交换模式空间与保持空间
command
可视化
'l'
-
可视化字符(GNU)
-
示例
sed -n 'l' test1 #可视化打印所有字符(包括特殊字符)
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin$
条件分支
'T '(GNU)
-
条件分支
-
示例
sed '/root/T;s/.*//' test1 #仅当行不匹配 root 时执行替换
root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin
awk
- **功能:**逐行扫描的文本处理引擎,用于字段拆分、统计汇总与报表生成
- 格式:awk [选项] 'BEGIN{预处理} 模式{动作} END{后处理}' 文件 ...
输入控制
-F <sep>
-
指定输入字段分隔符
-
示例
awk -F ':' '{print $1}' /etc/passwd #以冒号为列分隔,输出第一列用户名
root
bin
daemon
-v FS=','
-
脚本内设置输入分隔符
-
示例
awk 'BEGIN{FS=":"}{print $3}' /etc/passwd #同 -F: 在脚本内部使用
0
1
2
-v RS='\n\n'
-
自定义记录分隔符
-
示例
awk -v RS="\n\n" '{print NR,$0}' /etc//login.defs
#将连续空行(\n\n)视为记录分隔符,文件被分成多个"块"1 #
Please note that the parameters in this configuration file control the
behavior of the tools from the shadow-utils component. None of these
tools uses the PAM mechanism, and the utilities that use PAM (such as the
passwd command) should therefore be configured elsewhere. Refer to
/etc/pam.d/system-auth for more information.
2 # REQUIRED
输出控制
-v OFS=','
-
设置输出字段分隔符
-
示例
awk -v OFS=',' 'BEGIN{FS=":"}{print 1,3}' test1 # 列间用逗号输出
root,0
bin,1
daemon,2
-v ORS='\t'
-
设置输出记录分隔符
-
示例
awk -v ORS="\t" '{print $0}' test1 #所有行用制表符 \t 拼接成单行输出
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 sync:x:
脚本方式
-f script.awk
-
从文件加载 awk 脚本
-
示例
echo 'BEGIN{FS=":"}{print 1}' > script.awk #准备测试脚本,格式为BEGIN{}pattern { action }END{} echo 'BEGIN{FS=":"}{print 2}' >> script.awk
awk -f script.awk test1 #处理复杂逻辑时,将脚本写入文件
root
x
bin
x
兼容选项
-posix
-
禁用 GNU 扩展特性,强制兼容 POSIX 标准
-
示例
awk --posix 'BEGIN{FS=":"}{print $0}' test1
#确保脚本在不同系统(如 macOS、BSD)的 awk 上可移植
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
内置变量
FS
-
输入字段分隔符
-
示例
awk 'BEGIN{FS=":"}{print $7}' /etc/passwd #以冒号分隔字段
/bin/bash
/sbin/nologin
/sbin/nologin
OFS
-
输出字段分隔符
-
示例
awk 'BEGIN{FS=":"; OFS="\t"} {print 1,3}' test1 #输出列间用制表符分隔
root 0
bin 1
daemon 2
RS
-
输入记录分隔符
-
示例
awk 'BEGIN{RS="/"}{print $1}' test1 # 以
/
分隔记录
root:x:0:0:root:
root:
bin
ORS
-
输出记录分隔符
-
示例
awk 'BEGIN{ORS=" "} {print $0}' test1 #所有行用空格拼接成一行
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 sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/
NR
-
当前处理的总行号(跨文件累加)
-
示例
awk 'END{print NR}' test1 #输出文件总行数
24
FNR
-
文件内行号
-
示例
awk '{print FILENAME,FNR,$0}' test1 #输出格式: [文件名] [行号] [内容]
test1 1 root:x:0:0:root:/root:/bin/bash
test1 2 bin:x:1:1:bin:/bin:/sbin/nologin
test1 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
NF
-
当前记录的字段数量(列数)
-
示例
awk 'NF>=3 {print $0}' test1 #只输出列数≥3的行
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
$NF
-
最后一列
-
示例
awk -F: '{print $NF}' /etc/passwd #输出所有用户的登录shell
/bin/bash
/sbin/nologin
/sbin/nologin
1...n
-
第 n 列
-
示例
awk -F: '{print 1,3}' test1 #输出每行的第1列和第3列
root 0
bin 1
daemon 2
$0
-
整行
-
示例
awk '/root/{print $0}' test1 #输出包含"root"的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
FILENAME
-
当前正在处理的文件名
-
示例
awk '{print FILENAME,$0}' test1
test1 root:x:0:0:root:/root:/bin/bash
test1 bin:x:1:1:bin:/bin:/sbin/nologin
test1 daemon:x:2:2:daemon:/sbin:/sbin/nologin
ARGC / ARGV
-
ARGC :命令行参数个数
-
ARGV :参数值数组(ARGV[0]=awk, ARGV[1]=第一个文件)
-
示例
awk 'BEGIN { #输出处理文件的名字
for(i=1; i<ARGC; i++)
print "处理文件:", ARGV[i]
}' test1 patters.txt
处理文件: test1
处理文件: patters.txt
ENVIRON["VAR"]
-
访问系统环境变量
-
示例
awk 'BEGIN{print "家目录:", ENVIRON["HOME"]}' #输出当前用户的家目录
家目录: /root
预处理 / 后处理
BEGIN {}
-
预处理块
-
示例
awk 'BEGIN{print "Hello !"}' #在所有行读取前执行一次,常用于初始化变量或打印表头
Hello !
END {}
-
后处理块
-
示例
awk 'END{print NR}' test1 $在所有行处理后执行一次,常用于输出统计结果(如总和)
24
字符串函数
length(s)
-
字符串长度
-
示例
awk -F/ '{print length(2),0}' test1 #输出第二列的字符数
5 root:x:0:0:root:/root:/bin/bash
4 bin:x:1:1:bin:/bin:/sbin/nologin
5 daemon:x:2:2:daemon:/sbin:/sbin/nologin
substr(s,m,n)
-
截取子串
-
示例
awk -F/ '{print substr(0, 3, 5),0}' test1 #从每行第 3 个字符开始截取 5 个字符
ot:x: root:x:0:0:root:/root:/bin/bash
n:x:1 bin:x:1:1:bin:/bin:/sbin/nologin
emon: daemon:x:2:2:daemon:/sbin:/sbin/nologin
gsub(r,s[,t])
-
全局替换
-
示例
awk '{gsub(/root/,"ROOT",$0); print}' test1 #将整行所有 root 替换为 ROOT
ROOT:x:0:0:ROOT:/ROOT:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sub(r,s[,t])
-
首次替换
-
示例
awk '{sub(/root/,"ROOT",$0); print}' test1 #仅替换第一列第一个 root
ROOT:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
index(s,sub)
-
子串位置
-
示例
awk '{print index($0,"root")}' test1 #输出 root 首次出现的位置,未找到返回 0
1
0
0
0
0
0
0
0
0
27
match(s,r)
-
正则匹配
-
示例
awk 'match($0,/root/){print RSTART,RLENGTH}' test1 #若行中包含 root,输出匹配起始位置和长度
1 4
27 4
split(s,arr,sep)
-
字符串分割
-
示例
awk '{split($0,a,":"); print a[1]}' test1 #按冒号分割行,输出第一段
root
bin
daemon
sprintf(fmt,...)
-
格式化输出
-
示例
awk 'sprintf("%-10s %5d",1,3)' test1 #生成格式化文本
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
数值 / 日期函数
int()
-
取整
-
示例
awk -F: '{print int($3/2)}' test1 #将第三列除以 2 后取整
0
0
1
sqrt()
-
数值函数
-
示例
awk 'BEGIN{{print sqrt(16)}}' #计算平方根
4
strftime()
-
格式化时间
-
示例
awk 'BEGIN{print strftime("%F")}' #输出当前日期
2025-07-14
数组
arr[idx]=val
-
关联数组
-
示例
awk 'BEGIN{a["root"]="/bin/bash"; print a["root"]}' #创建键值对并输出值
/bin/bash
for (i in arr)
-
遍历数组
-
示例
awk 'BEGIN{for(i in ENVIRON) print i,ENVIRON[i]}' #遍历环境变量数组,输出所有键值对
BASH_FUNC_which%% () { ( alias;
eval {which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot @
}
AWKPATH .:/usr/share/awk
delete arr[i]
-
删除元素
-
示例
awk 'BEGIN { #删除 PATH 后打印所有剩余环境变量
delete ENVIRON["PATH"]
for (key in ENVIRON)
print key "=" ENVIRON[key]
}'
BASH_FUNC_which%%=() { ( alias;
eval {which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot @
}
AWKPATH=.:/usr/share/aw
in
运算符
-
键存在判断
-
示例
#检查用户是否存在
awk -F: '
BEGIN {
valid_users["root"] = 1
valid_users["daemon"] = 1
}
(1 in valid_users) { print "Valid user:", 1, "UID:", $3
}
' test1
Valid user: root UID: 0
Valid user: daemon UID: 2
流程控制
next
-
跳过当前行
-
示例
awk '/root/{next}{print}' test1 #若行包括 root 则跳过
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
getline
-
读取下一行
-
示例
awk '{getline n; print $0, n}' test1 #读取下一行存入变量 n,打印当前行和下一行(合并两行)
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 sync:x:5:0:sync:/sbin:/bin/sync
exit [code]
-
提前退出
-
示例
awk '/daemon/{exit 1}{print $0}' test1 #遇到包含 daemon 的行时立即退出,返回状态码 1
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
条件表达式
? :
-
三元运算
-
示例
awk '{print ($3>1000)?"big":"small"}' test1
#若第三列值大于 1000 输出 "big",否则输出 "small"
small
small
small