Linux sed命令使用笔记

124 篇文章 8 订阅

sed 通常用于过滤文本,即它接受文本输入,对其执行一些操作(或一组操作),然后输出修改后的文本。sed 通常用于使用模式匹配或替换文件中多次出现的字符串来提取文件的一部分。

Linux sed 命令是利用脚本来处理文本文件。
sed 可依照脚本的指令来处理、编辑文本文件。
Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

使用场景

我就讲讲我本来的使用场景,我使用最多的场景就是编写shell脚本时会用到。使用sed可以自动化的编辑一些文本文件。

官方帮助文档

https://www.gnu.org/software/sed/manual/sed.html

语法

sed [-hnV][-e<script>][-f<script文件>][文本文件]

参数说明:

  • -e<script>--expression=<script> 以选项中指定的script来处理输入的文本文件。
  • -f<script文件>--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。
  • -h或–help 显示帮助。
  • -n或–quiet或–silent 仅显示script处理后的结果。
  • -V或–version 显示版本信息。

动作说明:

  • a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
  • c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
  • d :删除,因为是删除啊,所以 d 后面通常不接任何东东;
  • i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
  • p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
  • s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!

示例

ubuntu切换国内的源

一般情况下,将 /etc/apt/sources.list 文件中 Ubuntu 默认的源地址 http://archive.ubuntu.com/ 替换为 http://mirrors.ustc.edu.cn/ 即可。
如果手动编辑,要输入很多指令,还会出错操作失误。

使用sed一行命令就可以实现了。

sudo sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list

这样就非常的方便。

删除文件中的第 4 行

sed '4d' input.txt > output.txt

在第 10-20 行将所有出现的 ‘hello’ 替换为 ‘world’

sed '10,20s/hello/world/' input.txt > output.txt

仅打印输入文件的第 45 行

sed -n '45p' file.txt

多个文件拼在一起输出1到20行

sed -n '1,20p' one.txt two.txt three.txt

输入指定字符结尾的行

sed -n '/bash$/p' /etc/passwd

Id删了指定字符结尾的行

input.txt内容如下;

boy
dog
girl
phone
age
sed '/dog$/Id' input.txt

删除命令: Id

i指定位置插入文本

input.txt内容如下;

a
b
c

要在b上面一行加个java

sed '/b/ijava' input.txt

a
java
b
c
基中i为插入指令java是插入的值

c将第 2 到第 9 行替换为单词 ‘hello’

seq 10 | sed '2,9c hello'
1
hello
10

命令c替换文本

整段文本的处理

处理段落等文本块(而不是逐行)的常用技术是使用以下构造:

sed '/./{H;$!d} ; x ; s/REGEXP/REPLACEMENT/'

第一个表达式/./{H;$!d}对所有非空行进行操作,并将当前行(在模式空间中)添加到保持空间。在除最后一行之外的所有行上,模式空间都被删除并重新开始循环。
其他表达式x和s仅在空行(即段落分隔符)上执行。该x命令将累积的行从保持空间取回模式空间。然后该 s///命令对段落中的所有文本(包括嵌入的换行符)进行操作。
示例:

$ cat input.txt
a a a aa aaa
aaaa aaaa aa
aaaa aaa aaa

bbbb bbb bbb
bb bb bbb bb
bbbbbbbb bbb

ccc ccc cccc
cccc ccccc c
cc cc cc cc

$ sed '/./{H;$!d} ; x ; s/^/\nSTART-->/ ; s/$/\n<--END/' input.txt

START-->
a a a aa aaa
aaaa aaaa aa
aaaa aaa aaa
<--END

START-->
bbbb bbb bbb
bb bb bbb bb
bbbbbbbb bbb
<--END

START-->
ccc ccc cccc
cccc ccccc c
cc cc cc cc
<--END

原文:
https://www.gnu.org/software/sed/manual/sed.html#Multiline-techniques

shell配合sed实现整段文本替换实例

写本文的原始需求:
需要修改一个非常长的Java文件,以下代码块

 @SuppressLint("AddJavascriptInterface")
    public void setMessagingEnabled(boolean enabled) {
      if (messagingEnabled == enabled) {
        return;
      }

      messagingEnabled = enabled;

      if (enabled) {
        addJavascriptInterface(createRNCWebViewBridge(this), JAVASCRIPT_INTERFACE);
      } else {
        removeJavascriptInterface(JAVASCRIPT_INTERFACE);
      }
    }

替换成:

    @SuppressLint("AddJavascriptInterface")
    public void setMessagingEnabled(boolean enabled) {//webview removeJavascriptInterface
        removeJavascriptInterface("searchBoxJavaBridge_");
        removeJavascriptInterface(accessibility);
        removeJavascriptInterface(accessibilityTraversal);
    }

原本我想使用Java代码代码来实现替换动作,或者使用lua脚本来实现这个事情。
考虑到这两种方式都是需要安装运行环境的。所以我就想能不能使用兼容性相对比较好的shell来实现。
就想到使用sed命令来实现了。
最终功能已经成功实现了,代码写的比较笨拙,仅供大家参考:

#!/bin/bash
#自动修改React Native Webview中的代码
#editFilePath='input.txt1'
editFilePath='../node_modules/react-native-webview/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java
'
#获取要修改的行号
setMessagingEnabledLine=$(sed -n '/public void setMessagingEnabled(boolean enabled) {$/=' ${editFilePath})
echo "查询关键字的位置:${setMessagingEnabledLine}"
if [[ "$setMessagingEnabledLine" == '' ]]; then
    echo "没有找到关键字,程序将要退出"
    echo "可能已经执行过 自动修改脚本了"
    exit
fi

#要修改的开始行号
startLine="$((setMessagingEnabledLine+1))"
#要修改的结束行号
endLine="$((startLine+10))"
index1="$((startLine-1))"
index2="$((startLine))"
index3="$((startLine+1))"
#删除方法体的内容
sed -i "${startLine},${endLine}d" ${editFilePath}
#增加第一行代码___用于格式化
sed -i "${index1}a________removeJavascriptInterface(\"searchBoxJavaBridge_\");" ${editFilePath} 
#增加第二行代码
sed -i "${index2}a________removeJavascriptInterface("accessibility");" ${editFilePath}
#增加第三行代码
sed -i "${index3}a________removeJavascriptInterface("accessibilityTraversal");"  ${editFilePath}
#用空格格式化一下
sed -i 's/________/        /' ${editFilePath}
#标记位做个标记访问重复处理
sed -i 's/public void setMessagingEnabled(boolean enabled) {$/public void setMessagingEnabled(boolean enabled) {\/\/webview removeJavascriptInterface/' ${editFilePath}
cat ${editFilePath}

兼容macOS与linux的方案

很遗憾有些命令在linux中运行正常,而放到macOS中执行就无法正常运行了。
比如:

sed -i "1,19d"  test.java

以上命令在Linux下是正常运行的,而在macOS中就不行了。报错如下:

sed -i "1,19d"  test.java
sed: 1: "test.java": undefined label 'est.java'

解决办法:

sed -i.bak -e "1,19d"  test.java

这样写就不报错了,但是修改文件后会自动备份文件。
如果不想生成备份文件,可以这样:

sed -i.bak -e "1,19d"  test.java && rm test.java.bak

这样会显的比较繁琐,但至少可以兼容两种系统。

相关阅读:
https://unix.stackexchange.com/questions/13711/differences-between-sed-on-mac-osx-and-other-standard-sed

第二种解决方案
调整mac下sed的用法,使其与linux一致
mac上安装gnu-sed

brew install gnu-sed
alias sed=gsed

调整后两系统下sed的用法完全一致。
链接:https://www.jianshu.com/p/87a57a12d5e6

参考

https://www.runoob.com/linux/linux-comm-sed.html

https://www.gnu.org/software/sed/

https://www.gnu.org/software/sed/manual/sed.html
《Mac OSX 上的 sed 与其他“标准”sed 之间的区别?》
https://unix.stackexchange.com/questions/13711/differences-between-sed-on-mac-osx-and-other-standard-sed
《mac上遇到的错误sed command a expects followed by text》
https://www.jianshu.com/p/87a57a12d5e6

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值