Bash
替代不寫入臨時文件的 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"
也就是說,我從一個文本文件中讀取值,然後根據這些值在另一個文本文件中進行一些更改。對大量值重複執行此操作。
您的問題不在於
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
標誌),直到你滿意它做了你想要的。¹ 由於我們使用的是bash,我們可以使用程序替換:
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