macOS下sed指定行插入字符串

MacOS:10.15.7

工作中需求:python调用shell脚本,脚本中要在文本文件中指定行下 添加 指定字符串。

如果不是想硬用MacOS下sed,用gsed与linux下的sed是几乎一样的。

Linux sed 命令是利用脚本来处理文本文件,示例文件

$ cat server.txt
P.1=pattern/test,1000000,100    # 要匹配的行 行号1
P.1.MergeCountEx=2
P.1.Merge.1=pattern/p1
P.1.Merge.2=pattern/p2

比如想在第一行后依次添加一些字符串,这些字符串存在一个record.txt下:

$ cat log.txt
P.1.Merge.1=pattern/ddd1
P.1.Merge.2=pattern/ddd2
P.1.Merge.3=pattern/ddd3
P.1.Merge.4=pattern/ddd4
P.1.Merge.5=pattern/ddd5
P.1.Merge.6=pattern/ddd6

最终希望server.txt变成:

$ cat server.txt
P.1=pattern/test,1000000,100 
P.1.MergeCountEx=6
P.1.Merge.1=pattern/ddd1
P.1.Merge.2=pattern/ddd2
P.1.Merge.3=pattern/ddd3
P.1.Merge.4=pattern/ddd4
P.1.Merge.5=pattern/ddd5
P.1.Merge.6=pattern/ddd6

思路

  • 1. 先匹配制定模式行号,通过 sed -n "/模式/=" 文件
begin=$(sed -n "/P.1=pattern/=" server.txt)    # begin -> 1

定位行号,MacOS下没问题。

  • 2. 清除.Merge的内容 (以防万一,不在原文件上进行修改,放到server.1.txt中)
sed "/P.1.Merge.*/d" server.txt > server.1.txt

清除内容,macOS下没问题。

$ cat server.1.txt
P.1=pattern/test,1000000,100 

只剩一行了,接下来先添加每一行,在所有行添加好了以后再添加Count那一行。

先试试随便添加一串字符串

  • 3. 在此行号后添加一串字符串 ,如"string",Linux下
sed -i "${begin} a\\string" server.1.txt

能够成功,其中-i表示在原文件下修改,a表示添加行,多加的‘\’为了防止后面的字符串被转义

但是MacOS下报错:

$ sed: 1: "server.1.txt": unterminated substitute in regular expression

“正则表达式中未终止替换“,看到这篇文章提到:要加上 -e 替换原文件,

加入后执行:

sed -i -e "${begin} a\\string" server.1.txt

报错:

sed: 1: "1 a\string": extra characters after \ at the end of a command

“在'\'后的命令末尾额外字符“?

在终端测试了一下,在输入‘\’后系统会认为命令没有结束,光标移动到下一行,要接着输入后面的字符。

改:

sed -i -e "${begin} a\\
string" server.1.txt

没有报错,我们再来看一下server.1.txt中是不是我们想要的结果:

$ cat server.1.txt
P.1=pattern/test,1000000,100
string%

除了有一个'%'外,它好像没有问题,再加一行试试,还在第一行后面加

sed -i -e "${begin} a\\
test" server.1.txt
$ cat server.1.txt
P.1=pattern/test,1000000,100
teststring

可以看到,'%'消失了,但是它没有换行,不是我们预期的,再加个换行试试看?

sed -i -e "${begin} a\\
string" server.1.txt
sed -i -e "${begin} a\\
test\\
" server.1.txt
$ cat server.1.txt
P.1=pattern/test,1000000,100
string

完事,先添加string,再加test,那么我们可以把record倒着插入,也可以每插入一行就将要插入的行数+1,我选择了后者。

  • 4. 把record插入进来
index=${begin}
cat record.txt | while read line
    sed -i -e "${index} a\\
    $line\\
    " server.1.txt
    let "index+=1"
$ cat server.1.txt
P.1=pattern/test,1000000,100
P.1.Merge.1=pattern/ddd1
P.1.Merge.2=pattern/ddd2
P.1.Merge.3=pattern/ddd3
P.1.Merge.4=pattern/ddd4
P.1.Merge.5=pattern/ddd5

咋少了一行。。。在record最后加一行空行完事。

  • 5. 加上最后汇总的那一行
count=$((index-begin))
sed -i -e "${begin} a\\
P.1.MergeCountEx=${count}\\
" server.1.txt
$ cat server.1.txt
P.1=pattern/test,1000000,100
P.1.MergeCountEx=6
P.1.Merge.1=pattern/ddd1
P.1.Merge.2=pattern/ddd2
P.1.Merge.3=pattern/ddd3
P.1.Merge.4=pattern/ddd4
P.1.Merge.5=pattern/ddd5
P.1.Merge.6=pattern/ddd6

打完收工。

整个shell文件

begin=$(sed -n "/P.1=pattern/=" server.txt)
index=$begin
echo ${index}
sed "/P.1.Merge.*/d" server.txt > server.1.txt
cat log.txt | while read line
    sed -i -e "${index} a\\
    $line\\
    " server.1.txt
    let "index+=1"
echo $index