sed -i 的替代方案,不写入临时文件

sed -i 的替代方案,不写入临时文件

我有几个编辑模板文本文件的脚本,通过删除“标签”并将其替换为数字等。为此,我使用

sed -i

命令。但是,我在执行脚本的服务器上遇到写入/读取时间问题,导致脚本需要很长时间才能运行,因为 sed -i 命令会在每次执行时将临时文件写入磁盘。

我是否可以使用另一种方法,即每次替换时都不会将临时文件写入磁盘?文本文件是否可以在内存中编辑,并且只有在执行所有替换后才写入,或者我可以将多个替换堆叠到同一个 sed 命令中吗?

为了澄清,脚本的形式如下:

input=shiftLeft.txt
while IFS= read -r line
do
    sed -i "s/install, element = $line, at=/install, element = $line, at= -0.001 +/g" processedFiles/layoutDB.seq
done < "$input"

也就是说,我从一个文本文件中读取值,然后根据这些值在另一个文本文件中进行一些更改。对于大量值重复执行此操作。

答案1

您的问题不在于sed -i创建许多临时文件,而是您使用同一输入文件多次运行它,并且每个文件都会为输出创建一个临时文件,如下strace所示:

execve("/bin/sed", ["sed", "-i", "-e", "", "/tmp/foo"], 0x7fff10da5288 /* 36 vars */) = 0
openat(AT_FDCWD, "/tmp/foo", O_RDONLY)  = 3
openat(AT_FDCWD, "/tmp/sedVdjaBk", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
rename("/tmp/sedVdjaBk", "/tmp/foo")    = 0
+++ exited with 0 +++

解决方案是只运行sed -i一次。

为此,首先编写一个sed将输入文件转换为sed程序的命令。那看起来像:

sed -e 's!.*!s/install, element = &, at=/install, element = &, at= -0.001 +/g!"

(如果输入文件包含正则表达式有效字符,例如,我们可以改进这一点s/install, element = &, at=/\& -0.001 +/g,但这超出了这个问题的范围)。

对此进行测试以确保您对生成的脚本感到满意。

然后我们需要另一个sed使用转换后的文本作为其程序文件。我们可以通过告诉它从标准输入读取程序来做到这一点(尽管还有其他选择):

sed -e 's!.*!s/install, element = &, at=/install, element = &, at= -0.001 +/g!' \
    shiftLeft.txt |
sed -f - -i processedFiles/layoutDB.seq

再次测试这个(不带-i标志),直到您满意它达到您想要的效果为止。


¹ 因为我们正在使用,我们可以使用过程替换:

sed -f <(sed -e 's!.*!s/install, element = &, at=/install, element = &, at= -0.001 +/g!' shiftLeft.txt) \
    -i processedFiles/layoutDB.seq

在标准 shell 中,我们需要将转换后的文本捕获为字符串,并将其作为命令行脚本提供:

sed -e "$(sed -e 's!.*!s/install, element = &, at=/install, element = &, at= -0.001 +/g!' shiftLeft.txt)" \
    -i processedFiles/layoutDB.seq

答案2

不要在 shell 循环中重复调用 sed,只需调用 awk 一次,例如(未测试,因为您没有提供任何示例输入/输出来测试)使用 GNU awk 进行“就地”编辑和 match() 的第三个参数:

awk -i inplace '
    NR==FNR { lines[$0] }
    (FNR>NR) && match($0,/(.*install, element = )([^,]+)(, at=)/,a) && (a[2] in lines) {
        $0 = a[0] " -0.001 +"
    }
    { print }
' shiftLeft.txt processedFiles/layoutDB.seq

根据您的输入/输出的情况,可能有更好的方法来做到这一点。

相关内容