sed流编辑器中使用变量替换以及执行外部命令

2023-05-16

在使用sed对日志或者其它文本进行parse的过程当中,有时候我们需要引用外部变量的值,
 
或者获取一个shell命令执行的结果,以便达到更加可观的输出结果。这里介绍如何做到。
 

sed 流编辑

1  sed命令及其语法
sed命令是将一系列的编辑命令应用于一批文本的理想工具. sed命令拥有非交互式和高效的特点,可以为用户节约大量的时间. 本节将介绍sed命令的基础知识. 

1.1  sed命令以及语法
sed命令是一个非交互式的文本编辑器,它可以对来自文本文件以及标准输入的文本进行编辑. 其中,标准输入可以是来自键盘, 文件重定向, 字符串, 变量或者是管道的文本. 
sed命令会从文件或者标准输入中一次读取一行数据,将其复制到缓冲区,然后读取命令行或者脚本的编辑子命令,对缓冲区中的文本行进行编辑. 重复此过程,一直到所有的文本行都处理完毕. 


1.2  sed命令的工作方式
首先,用户可以在命令行直接执行sed命令,其基本语法如下:
sed [options] commands inputfile
其中commands请参考2节内容,,每一个commands由"定位 sed操作 可选参数"组成;其中定位可以省略,可选参数也可以根据实际情况省略;如果省略了定位将对所有行进行操作,否则只对匹配到的行进行操作;
定位分为:1.行号定位;2.正则表达式定位;

sed命令的选项
-n  取消默认输出,只输出定位匹配到的行
-e  允许执行多个子命令
-f  从脚本中读取命令
-i  直接修改原始文件
-l  指定行的长度
-r  在脚本中使用扩展的正则表达式
-u  最低限度的缓存输入与输出

总之,sed命令的使用方式为
sed [sed命令的选项(可选)] "定位部分(可选) sed的操作命令 [sed操作的(可选)参数]" sed操作的文件名


其次,用户可以将sed操作命令写入脚本文件,然后通过sed命令读取该文件并且执行其中的命令,其基本语法如下:
sed [options] -f script inputfile
最后,用户通过将sed的操作命令写入文件,然后将该脚本文件授予用户执行权限,其基本语法如下:
./scrpt inputfile
其中,script代表保存sed命令的脚本文件. 在前面已经讲过,在脚本文件中,用户应该在#!符号后面执行该脚本的解释器,因此在这种方式下,sed脚本文件的第一行应该如下:
#! /bin/sed

1.3  使用行号定位文本行
1.定位某个特定的行,语法如下:
x
2.定位某段连续的行,语法如下:
x,y
3.指定起始行和步长
first~step
4.指定文件的第一行和最后一行
第1行:
1
最后1行:
$
5.指定某行后面的几行,语法如下:
x,+n

1.4  使用正则表达式定位文本行
除了使用行号定位文本行之外,sed命令还支持正则表达式定位. 
sed命令中,正则表达式的语法如下:
/regexp/

两个斜线之间的regexp表示正则表达式,其中常用的正则表达式字符如下
普通字符   字符本身就匹配字符本身,如/abc/就定位包含abc的行
.          匹配任意字符
^          匹配行首字符
$          匹配行尾字符
[]         匹配方括号中的任意单个字符
[^]        匹配不出现在方括号中的任意单个字符
\n         匹配换行符
*          表示前置表达式重复了0次或多次
+          表示前置表达式重复了1次以上
?          表示前置表达式重复了0次或1次
{i}        表示前置表达式重复出现i次
{i,}       表示前置表达式至少重复出现i次
{i,j}      表示前置表达式至少匹配i次,最多匹配j次
匹配会扩展到可能的最长的文本量

注意$字符在正则表达式中匹配行尾,在行号定位中表示最后一行

2  sed命令的常用操作
除了定位参数之外,sed命令的另外一个组成部分就是编辑命令. 常用的编辑命令有打印, 插入, 删除以及替换等,本节将介绍如何在sed命令使用这些编辑命令. 
2.1  sed编辑命令基本语法
sed命令的基本语法如下:
[address1[,address2]] cmd [argument]
即"定位 sed操作 可选参数"共同组成sed的编辑命令command;
使用时,在command前加上sed的选项,后面加上操作的文件;

2.2  选择文本
在sed命令中,选择文本行主要通过位置参数来完成,基本语法如下:
[address1[ ,address2]] p
在上面的语法中,address1和address2都是位置参数. 如果省略位置参数,则表示选择整个文件. 子命令p表示将缓冲区中的文本行执行输出操作,即打印(print)缓冲区中的文本. 
在上面的命令中只有"定位 sed操作(p打印)",省略了操作的参数;

#! /bin/bash
#输出1~3行,不使用-n选项
sed '1,3p' students.txt
echo "===================================="
#输出1~3行,使用-n选项
sed -n '1,3p' students.txt

#! /bin/bash
#使用正则表达式定位
result=`sed -n '/^20020017/ p' students.txt`
echo "$result"

2.3  替换文本
使用sed命令,可以很方便地对文本文件中指定的文本进行替换操作. 文本的替换需要使用s子命令,其语法如下:
[address1[ ,address2]] s/pattern/replacemen/[flag]
在上面的语法中,address1与address2都是位置参数,关于它们的用法请参见前面的几个小节. 在s命令中,位置参数通常会被省略,表示在所有的文本行中进行替换操作,其语法如下:
s/pattern/replacemen/[flag]
s子命令表示执行替换(substitute)操作. pattern为使用正则表达式表示的匹配模式,replacement为用来替换的由一般字符组成的字符串,如果含有&则表示引用模式(子字符串). 

在s命令中,斜线/是参数分隔符,各个参数之间并不一定要使用斜线/分割,还可以使用出空格以及换行符以外的其他任意字符;s命令会将紧跟在后面的那个字符作为参数分隔符;

flag为替换标志,会影响到s命令的行为
g            全局匹配,会替换文本行中所有符合规则的字符串
n十进制数字  表示替换第n个符合规则的字符串
p            替换第1个符合规则的字符串,并输出到标准输出
w            替换第1个符合规则的字符串,并写入到磁盘文件
空           默认替换第1个符合规则的字符串;

#! /bin/bash
echo "substitute the first pattern."
#只将每行中第1次出现的小写字母e替换为大写字母E
result=`sed 's/e/E/' students.txt`
echo "$result"
echo "substitute all the patterns."
#将每一处的小写字母e都替换为大写字母E
result=`sed 's/e/E/g' students.txt`
echo "$result"


#! /bin/bash
#替换第1~3行中的所有的小写字母e为大写字母E
result=`sed '1,3 s/e/E/g' students.txt`
echo "$result"

#! /bin/bash
#使用混合位置参数
result=`sed '1,/^200200167/ s/e/E/g' students.txt`
echo "$result"

#! /bin/bash
#将文件中的HTML标记替换为空
result=`sed 's/<[^>]*>//g' html.txt`
echo "$result"

#! /bin/bash
#引用与模式相匹配的子串
result=`sed 's/string/long &/' demo1.txt`
echo "$result"

#! /bin/bash
#通过数字来引用模式中的子串
result=`sed 's/\(This\) \(is\) \(a\) \(string\)/\2 \1 \3 \4/' demo1.txt`
echo "$result"

2.4  删除文本
sed提供了d子命令来实现文本行的删除(delete),其语法如下:
[address1[ ,address2]] d
在上面的语法中,2个位置参数的涵义以及用法请参见前面的内容. 
命令d表示删除位置参数指定的行. 如果省略位置参数,则表示删除文本文件中的所有的行. 
在执行删除操作时,sed命令的会首先读取一行文本到缓冲区,然后将符合位置参数的文本行删除,接着再读取并处理下一行. 下面的例子演示了如何删除指定的文本行. 

#! /bin/bash
#删除第1行
result=`sed -e '1 d' students.txt`
echo "$result"

#! /bin/bash
#删除最后一行
result=`sed -e '$ d' students.txt`
echo "$result"

#! /bin/bash
#删除1~4行
result=`sed -e '1,4 d' students.txt`
echo "$result"
echo "==============================="
#删除奇数行
result=`sed -e '1~2 d' students.txt`
echo "$result"
echo "=============================="
#删除偶数行
result=`sed -e '0~2 d' students.txt`
echo "$result"
echo "============================="
#删除从第1行开始,一直到以200200172开头的行
result=`sed -e '1,/^200200172/ d' students.txt`
echo "$result"
echo "============================"
#删除从第4行开始,一直到最后一行的所有行
result=`sed '4,$ d' students.txt`
echo "$result"

2.5  追加文本
所谓追加文本,是指将某些文本插入到某个位置的后面. sed命令提供了a子命令来实现文本的追加(append),其基本语法如下:
[address1] a string
从上面的语法可以得知,子命令a最多只能使用一个位置参数. 参数string表示将要追加的文本. a子命令会将string代表的文本插入到address1所表示的位置的后面. 这一点也是追加文本与后面将要介绍的插入文本的区别. 

#! /bin/bash
#在第2行后面追加文本
result=`sed '2 a 200200109      Tom' students.txt`
echo "$result"

#! /bin/bash
#在以200200110开头的文本行后面追加文本
result=`sed '/^200200110/ a 200200109    Tom' students.txt`
echo "$result"

2.6  插入文本
插入文本的操作与追加文本非常相似,只是插入的位置不同. 
追加文本是在位置参数指定的位置的一行后面插入文本,而插入文本则是位置参数指定的位置的一行前面插入文本. 在sed命令中,子命令i用来实现文本的插入,其语法如下:
[address1] i string
与子命令a一样,子命令i也是最多只能使用一个位置参数. 位置参数address1用来指定要插入文本的位置,子命令i表示当前的操作是插入文本,参数string表示将要被插入的文本. 

#! /bin/bash
#在以200200110开头的文本行前面插入文本
result=`sed '2 i 200200109      Tom' students.txt`
echo "$result"

3  组合命令
sed命令支持将多个子命令组合在一起使用,这一点非常重要,因为在通常情况下,用户需要对文本进行多个不同的操作. 如果不支持组合命令的话,则需要使用多个sed命令来完成;如果使用组合命令,则可以在一条sed命令中将这些操作完成. 本节将介绍sed中的组合命令的使用方法. 

3.1  使用-e选项执行多个子命令
sed命令的-e选项可以使得sed将跟在其后面的字符串作为子命令执行. 在前面的绝大部分例子中,由于都是一个子命令,所以将该选项省略. 但是,如果想要为sed命令同时指定多个子命令,则必须使用多个-e选项. 

#! /bin/bash
#将所有的小写字母e替换为大写字母,然后打印2~3行
result=`sed -n -e 's/e/E/g' -e '2,3 p' students.txt`
echo "$result"

3.2  使用分号执行多个子命令
用户还可以使用分号来将各个子命令隔开,其语法如下:
sed -e 'command1;command2...' filename
其中,command1以及command2等表示多个子命令,这些子命令之间用分号隔开. filename参数表示要处理的文本文件. 

#! /bin/bash
#使用分号隔开多个子命令
result=`sed -e 's/e/E/g; 2 i 200100001    Ellen' students.txt`
echo "$result"

3.3  对一个地址使用多个子命令
在某些情况下,用户需要对同一个地址使用多个子命令,例如,对某个文件的前20行进行多次替换操作等. sed命令提供了对同一个地址使用多个子命令的语法,如下:
address {
    command1
    command2
    command3
    ...
}

#! /bin/bash
#组合命令
result=`sed -n '1,5 {
    s/e/E/g
    s/a/A/g
    2 i 201303009 Tom
    p
}' students.txt`
echo "$result"

3.4  sed脚本文件
sed提供了-f选项,通过这个选项,sed命令可以从指定的脚本文件中读取子命令,然后对每个文本行依次执行各个子命令,其语法如下:
sed -f script
其中,script表示sed脚本文件. 
sed脚本的语法比较简单,就是将各个子命令依次列出来,不必使用引号. 如果将多条子命令写在同一行中,需要使用分号将其隔开. 另外,sed脚本文件支持代码注释,如果某一行以#开头,则表示该行为注释. sed脚本的注释仅限于行注释,不能跨行. 

 

sed中使用变量替换例子
 
1.sed命令使用双引号的情况下,使用$var直接引用
 
$ echo|sed "s/^/$RANDOM.rmvb_/g"
 29328.rmvb_

如果替换的变量内容中含有/符号则会提示如下错误,如
查找当前目录下的目录文件并将相对路径替换为绝对路径
find . -type f | sed -n "s/\./$PWD/p"
sed: -e expression #1, char 19: unknown option to `s'
从语法上看,没有任何问题;但由于变量中包含有“/”作为分隔符,这会和sed的替换操作的分隔符“/”引起混淆;所以,只要不使用“/”做分隔符就可以解决这个问题,如果使用“%”而不是“/”来作为sed的替换操作的分隔符,就不会出错。其实使用#或%或;作为分隔符也是可以的,只要不会与替换中有相同的而且不是元字符的特殊符号都是可以的;使用时可以根据情况灵活选择。
find . -type f | sed -n "s%\.%$PWD%p"
find . -type f | sed -n "s#\.#$PWD#p"

# 上面例子引用了一个环境变量$RANDOM的值
 
2.sed命令使用单引号的情况下,使用'"$var"'引用
 
类似,我们可以看到
 
$ echo|sed 's/^/'"$RANDOM"'.rmvb_/g'
 31338.rmvb_
 
sed中执行外部命令
 
1.sed命令使用单引号的情况下使用'`shell command`'或者'$(shell command)'引用命令执行的结果
 
还是以上面案例分析,例子如下
 
$ echo|sed 's/^/'`echo $RANDOM`'.rmvb_/g'
 8063.rmvb_
 

# 上面的例子使用了旧式的命令替换,也可以采用新式的命令替换方法,如下
 
$ echo|sed 's/^/'$(echo $RANDOM)'.rmvb_/g'
 18554.rmvb_
 

# 下面例子取用当前日期作为结果的一部分,如下
 
$ echo|sed 's/^/'$(date +"%Y%m%d")'.rmvb_/g'
 20120108.rmvb_
 

2.sed命令使用双引号的情况下直接`shell command`或者$(shell command)引用命令执行的结果
 

类似的,双引号的情况,如下
 
$ echo|sed "s/^/$(date +"%Y%m%d").rmvb_/g"
 20120108.rmvb_
 

# 使用环境变量$RANDOM以及旧式命令替换的例子
 
$ echo|sed "s/^/`echo $RANDOM`.rmvb_/g"
 4988.rmvb_
 
总结
 
在sed语句里面,变量替换或者执行shell命令,双引号比单引号少绕一些弯子

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

sed流编辑器中使用变量替换以及执行外部命令 的相关文章

随机推荐

  • 基于FFmpeg H264 + G711A 音视频裸流合并 MP4文件 ( G711A 转 AAC)

    由于 FFmpeg 只支持H264 43 AAC的mp4封装格式的 xff0c 并不支持H264 43 G711的mp4封装格式 所以需要将G711a转码成AAC格式的 然后封装成mp4文件 xff0c 但网上有说 通过修改movenc c
  • YOLOV3 网络结构学习笔记

    注 xff1a 本文非原创 xff0c 文章内容都是引用以下文章中 xff0c 本文只是记录学习笔记 yolo系列之yolo v3 深度解析 木盏的博客 CSDN博客 yolo3 YOLO v3算法详解 Atlas 的博客 CSDN博客 y
  • 基于人脸特征点实现疲劳检测

    为了有效监测驾驶员是否疲劳驾驶 避免交通事故的发生 提出了一种利用人脸特征点进行实时疲劳驾驶检测的新方法 对驾驶员驾驶时的面部图像进行实时监控 首先检测人脸 并利用ERT算法定位人脸特征点 然后根据人脸眼睛区域的特征点坐标信息计算眼睛纵横比
  • 基于 HPSocket , 实现 socket 通讯

    HPSocket HP Socket 是一套通用的高性能 TCP UDP HTTP 通信框架 xff0c 包含服务端组件 客户端组件和 Agent 组件 xff0c 广泛适用于各种不同应用场景的 TCP UDP HTTP 通信系统 xff0
  • windows 基于 MediaPipe 实现 PoseTracking

    MediaPipe是用于构建跨平台多模态应用ML管道的框架 xff0c 其包括快速ML推理 xff0c 经典计算机视觉和媒体内容处理 xff08 如视频解码 xff09 在2019年6月举行的CVPR大会 xff0c MeidaPipe正式
  • windows 基于 MediaPipe 实现 HandTracking

    OverView 感知手的形状和运动的能力可能是改善跨各种技术领域和平台的用户体验的重要组成部分 例如 xff0c 它可以构成手语理解和手势控制的基础 xff0c 还可以在增强现实中将数字内容和信息叠加在物理世界之上 虽然对人们来说很自然
  • DeepStream 部署 RTSP + scaled-yolov4 (tensorrtx)

    DeepStream应用程序将深度神经网络和其他复杂的处理任务引入到流处理管道中 xff0c 以实现对视频和其他传感器数据的近实时分析 从这些传感器中提取有意义的见解为提高运营效率和安全性创造了机会 例如 xff0c 摄像头是当前使用最多的
  • DeepStream 多路拉取RTSP视频流

    上一篇介绍DeepStream 如何集成Yolov4模型 xff0c 那么本篇介绍下如何实现读取多路RTSP 代码 主要代码参考 https github com belarbi2733 deepstream rtspsrc yolo详细代
  • 编码格式(关于utf-8,gb2312,gbk,big5等)

    计算机数据是以二进制的方式来存储 xff0c 符号代表文字 那么二进制数据表示的模式就是编码 xff0c 跟电报的加密解密是一个道理 xff0c 那么如何将这些数据转化成有效字符 xff0c 这就涉及到了编码格式 xff0c 一般常见的编码
  • Ubuntu配置桥接网络

    第一步 xff1a 点击虚拟机 xff0c 点击设置 第二步 xff1a 点击网络适配器 xff0c 选中桥接模式并确定 第三步 xff1a 点击编辑 xff0c 打开虚拟网络编辑器 xff0c 选中桥接模式 点击 网络属性 找到描述 xf
  • 基于 NCNN, 实现 yolov8

    记录下 基于 ncnn 实现 yolov8 的全部过程 修改 ultralytics nn modules py class Detect forward 和 class C2f forward span class token keywo
  • HRNet 训练自定义数据集

    基于 HRNet 训练人脸特征点数据集 INSTALL conda create n openmmlab span class token assign left variable python span span class token
  • Chatgpt 指令收集

    在使用 ChatGPT 时 xff0c 当你给的指令越精确 xff0c 它的回答会越到位 xff0c 举例来说 xff0c 假如你要请它帮忙写文案 xff0c 如果没给予指定情境与对象 xff0c 它会不知道该如何回答的更加准确 一 写报告
  • openEuler 安装图形桌面环境Gnome或DDE或UKUI

    由于openEuler系统主要针对服务器 xff0c 目前默认安装之后没有图形桌面环境 xff0c 需要的用户可以自己手动安装配置 这里推荐安装深度桌面DDE或优麒麟UKUI环境 安装gnome桌面 sudo dnf makecache s
  • Ubuntu更换国内镜像源

    由于Ubuntu官方镜像速度有限 xff0c 可以使用国内镜像加速更新和下载 xff0c 节约时间 常用的国内镜像有很多 xff0c 本人常用的有如下几个 xff0c 仅供参考 163镜像 mirrors 163 com 清华镜像 mirr
  • ubuntu-2204 gerrit ssh 报错Permission denied (publickey).分析及解决

    ubuntu 2204 gerrit ssh 报错Permission denied publickey 分析及解决 使用repo init sync下载代码时遇到报错 Permission denied publickey 分析排查步骤
  • 消息序列化工具-protobuf介绍及安装使用技巧

    简介 protobuf是google团队开发的用于高效存储和读取结构化数据的工具 xml json也可以用来存储此类结构化数据 xff0c 但是使用protobuf表示的数据能更加高效 xff0c 并且将数据压缩得更小 xff0c 大约是j
  • 消息序列化工具-为现代C++设计的jsoncpp介绍与使用技巧

    概述 JSON 的全称为 xff1a JavaScript Object Notation xff0c 顾名思义 xff0c JSON 是用于标记 Javascript 对象的 xff0c JSON 官方的解释为 xff1a JSON 是一
  • cppcheck代码检查工具安装与使用技巧

    cppcheck代码检查工具安装与使用技巧 Cppcheck 是一种 C C 43 43 代码缺陷静态检查工具 不同于 C C 43 43 编译器及很多其它分析工具 xff0c 它不检查代码中的语法错误 Cppcheck 可以检查非标准代码
  • sed流编辑器中使用变量替换以及执行外部命令

    在使用sed对日志或者其它文本进行parse的过程当中 xff0c 有时候我们需要引用外部变量的值 xff0c 或者获取一个shell命令执行的结果 xff0c 以便达到更加可观的输出结果 这里介绍如何做到 sed 流编辑 1 sed命令及