Linux“文本三剑客”之sed

“文本三剑客”中,grep是文本过滤器,而sed是基于行的文本流编辑器。
sed是将文件中的文本逐行读取到内存中进行处理。

  1. sed工作原理
  2. sed命令
    2.1 OPTION
    2.2 SCRIPT
  3. sed使用示例

1 sed工作原理

sed有两个工作空间,Pattern space(模式空间)和Hold space(保持空间)。


image.png

Pattern space 模式空间

sed会把文件内容的每一行复制一份出来放到自己的Pattern space中,在其中处理以后,处理的结果送到stdout(标准输出):

  1. 默认情况sed会处理每一行,但我们可以让sed处理只被模式(如正则表达式)匹配到的文本。
  2. Pattern space中被用户给出的模式匹配到的内容,则edit(编辑)后再送到stdout。
  3. 如果不能匹配,则不做任何编辑操作,直接输出到stdout。

Hold space 保持空间

Hold space用于在使用高级编辑功能时,实现与Pattern space空间中的内容进行追加、覆盖、互换等操作。后边高级编辑示例中会详细解释。

2 sed命令

sed - stream editor for filtering and transforming text
sed [OPTION]... 'SCRIPT' [input-file]...
sed命令需要将命令选项OPTION和处理脚本SCRIPT结合使用,来对文本进行特定的处理动作。

2.1 OPTION

  • -n:不输出模式空间的内容至屏幕stdout
    [默认情况下,会将不被pattern匹配到的内容直接输出到stdout,-n则不输出这部分内容]
  • -e script,--expression=script:多点编辑;
    默认只支持一个script(被pattern匹配到的内容将被执行的编辑命令),加-e可以指定多个script。
    如:sed -e 's@^#[[:space:]]*@@' -e '/^UUID/d' /etc/fstab
  • -f /PATH/TO/SED_SCRIPT_FILE
    SED_SCRIPT_FILE中,每行都有一个script,从文件中逐行读取script,省去-e的繁琐
  • -r,--regexp-extended:支持扩展正则表达式
  • -i[SUFFIX],--in-place[=SUFFIX]:直接编辑原文件(有风险,用之前先做备份)(sed默认不直接编辑原文件)。

2.2 SCRIPT

SCRIPT由"地址定界"和"编辑命令"两部分组成,和vi编辑器的末行模式命令相似。两部分中间无空格。

地址定界的语法格式
  1. 地址定界为空,表示全文;
  2. 单地址:
    N:指定一个行号,表示第N行;
    /PATTERN/:给出一个模式,表示被模式匹配到的每一行。
  3. 地址范围:
    M,N:表示从第M行到第N行;
    M,+N:表示从第M行开始,到往后N行之间的所有行(包含第M行);
    M,/PATTERN/:表示从第M行到被PATTERN匹配到的第一行之间的所有行
    /PATTERN1/,/PATTERN2/:表示从被PATTERN1匹配到的第一行,到被PATTERN2匹配到的第一行之间的所有行。
  4. 用“~”表示步进:
    如:1~2表示所有奇数行,2~2表示所有偶数行。
编辑命令
  1. d:delete pattern space,删除模式匹配到的内容(模式空间中的内容)
    d是一个特殊的操作
  2. p:print the current pattern space:打印模式匹配到的内容(模式空间中的内容)
    p也是一个特殊的操作,会将pattern匹配到的内容显示两遍,如果不加选项,显示结果为,模式空间中的全部内容+被pattern匹配到的内容;
    如果只想显示被pattern匹配的内容,配合使用-n选项,将不显示默认输出的模式空间全部内容。
  3. a \text:append,在模式匹配到的行后面追加文本“text”,支持使用\n(换行符号)实现多行追加(注意文本前用\转义)
  4. i:insert,在模式匹配到的行前面插入文本“text”,支持使用\n(换行符号)实现多行插入(注意文本前用\转义)
    比如,在fstab文件中所有以UUID开头的行前面加入注释:
    sed '/^UUID/i # Add device based on UUID.' fstab
  5. c \text:把匹配到的行替换为"text"(注意是整行替换!!);
  6. w /PATH/TO/SOMEFILE:保存模式匹配到的行至指定的文件中;
    例如:将fstab中所有以非#开头的行保存到当前目录下的fstab.new文件中:
    sed '/[#]/w fstab.new' fstab
  7. r /PATH/FROM/SOMEFILE:读取指定文件的内容至当前文件被模式匹配到的行后面;
    例如:将/etc/issue文件中的内容显示到fstab文件第3行的后面:
    sed '3r /etc/issue' fstab
  8. =:为模式匹配到的行打印行号(在行的前面另起一个新行来打印行号);
    例如:将fstab中所有以UUID开头的行都打印行号:
    sed '/^UUID/=' fstab
  9. !:条件取反(!放在地址定界和编辑命令之间)
    地址定界!编辑命令
    例如:前边有个例子,“将fstab中所有以非#开头的行保存到当前目录下的fstab.new文件中”
    我们使用 “sed '/[#]/w fstab.new' fstab”;
    在这里可以这样“ sed '/^#/!w fstab.new' fstab”,它表示所有#号开头的行都不写入fstab.new文件,即非#开头的行就写入。
  10. s///:查找替换,其分隔符可自行指定,常用的有s@@@,s###等;
    替换标记:
    g:全局替换
    w /PATH/TO/SOMEFILE:将替换成功的结果保存至指定文件中;
    p:显示替换成功的行;
高级编辑命令

高级编辑命令用于Pattern space和Hold space中内容的追加、覆盖和互换,有以下几个:

  1. Pttern space --> Hold space
    h:把模式空间中的内容覆盖至 > 保持空间(hold space)中;
    H:把模式空间中的内容追加至 >> 保持空间(hold space)中;
  2. Hold space --> Pattern space
    g:把保持空间中的内容覆盖至 > 模式空间中;
    G:把保持空间中的内容追加至 >> 模式空间中;
  3. 模式匹配的下一行 --> Pattern space
    n:覆盖读取匹配到的行的下一行至 > 模式空间中
    N:追加读取匹配到的行的下一行至 >> 模式空间中
  4. Pattern space <--> Hold space
    x:把模式空间中的内容与保持空间中的内容互换;
  5. 删除Pattern sapce中的行
    d:删除模式空间中的行
    D:删除多行模式空间中的所有行(多行模式空间比如,N命令追加到模式空间中行)

3 sed使用示例

普通编辑命令示例

sed是否用得好,主要是看SCRIPT的编写能力。

  1. 删除/etc/grub2.cfg文件中所有以空白字符开头的行的行首的所有空白字符:
    sed 's@^[[:space:]]\+@@' /etc/grub2.cfg
  2. 删除/etc/fstab文件中所有以#开头的行的行首的#号及#后边的所有空白字符:
    sed 's@^#[[:space:]]*@@' /etc/fstab
  3. 输出一个绝对路径给sed命令,要求取出其目录名,类似dirname命令执行结果:
    echo "/var/log/messages" | sed 's@[^/]\+/\?$@@'
    或使用-r选项支持扩展正则表达式:
    echo "/var/log/messages" | sed -r 's@[^/]+/?$@@'

高级编辑命令示例与命令解析

要使用sed的高级编辑命令,需要对sed的工作流程非常熟悉。

  • sed -n 'n;p' FILE
    显示偶数行(;分号用来分隔多个命令)
    命令解析:
    因为是n;p,没有地址定界,表示逐行读取所有内容。
    1、首先读取第1行到pattern space,遇到第一个命令是n,覆盖读取下一行(也就是第2行)到pattern space,所以现在pattern space中的内容变为第2行(第1行被覆盖掉);
    2、然后是p命令,将pattern space中的第2行显示出来;
    3、接着读取第3行到pattern space,同上,显示第4行;
    4、以此类推,显示所有偶数行。

注意:如果没有-n选项,则将显示全部内容,并且偶数行显示两遍。

  • sed '1!G;h;$!d' FILE
    逆序显示文件内容,相当于tac
    命令解析:
    1、读取第1行到pattern space,先碰到“1!G”命令,表示第1行不做G操作;
    2、然后碰到下一个命令“h”,表示将pattern space中的内容覆盖至hold space,就是将第1行内容复制到了hold space中;
    3、接下来碰到“$!d”命令,表示将pattern space中不是最后一行的内容全部删除,pattern space中当前还有第1行的内容,则将其删除。第1行的读取到此结束。
    4、接着读取第2行,“1!G”命令将hold space中的内容(第1行的内容)覆盖至pattern space,所以目前pattern space中的内容变为“第2行+第1行”;
    5、然后碰到“h”命令,将pattern space中的内容(第2行+第1行)复制到hold space中(hold space中原来的第1行内容被覆盖掉),所以现在hold space中的内容为“第2行+第1行”;
    6、下一个命令“$!d”,同上,将pattern space中的“第2行+第1行”内容删除。
    第2行的读取到此结束。
    7、以此类推,知道读取第n-1行结束时,hold space的内容为“第n-1行+第n-2行....第2行+第1行”,pattern space为空;
    8、最后读取第n行,“1!G”命令将hold space内容追加到pattern space,则pattern space内容变为“第n行...第1行”;
    9、“h”命令将pattern space的内容覆盖复制到hold space,则现在hold space的内容为“第n行...第1行”;
    10、最后碰到“$!d”命令,因为是最后一行,则不删除pattern space的内容,所以pattern space中的内容还是“第n行...第1行”。
    11、读取完全部内容后,默认输出pattern space中的全部内容,即“第n行...第1行”,将原内容逆序显示!

  • sed '$!d' FILE
    取出最后一行,相当于tail -1
    命令解析:
    1、读取第1行到pattern space,pattern中的命令为“$!d”(不是最后一行,则删除),所以把第1行从pattern space中删了
    2、依次类推,一直删到倒数第2行;
    3、到最后一行,不删了,保留在pattern space中,然后输出到stdout。

  • 其他几个高级编辑命令示例
    sed '$!N;$!D' FILE:显示最后两行,相当于tail -2
    sed '/^$/d;G' FILE:删除原有所有空白行,再为所有非空白行后添加一个空白行
    sed 'n;d' FILE:显示奇数行;
    sed 'G' FILE:在原有的每行后方添加一个空白行;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Sed工具工作原理及特性 1. sed是流编辑器,每一次读取一行到内存中,即称之为模式空间(pattern spa...
    魏镇坪阅读 10,921评论 0 12
  • 本文承接之前写的三十分钟学会AWK一文,在学习完AWK之后,趁热打铁又学习了一下SED,不得不说这两个工具真的堪称...
    mylxsw阅读 4,382评论 3 74
  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,128评论 2 34
  • sed篇总共分成6章:(简书版) Sed&awk笔记之sed篇:简单介绍 Sed&awk笔记之sed篇:模式空间与...
    magic5650阅读 626评论 0 3
  • 时间不曾为我等待,生活没有那么简单。 我的喘息没有谁能听见,因为我出身平凡,所以要飞到更高,也许外面的世界没有想象...
    冰镇夏天阅读 229评论 0 6