簡體   English   中英

如何在Unix Shell腳本中用SED替換同一文件中的一行?

[英]How to Replace a line in the same file by SED in Unix Shell scripting?

在參考這個問題在第一和第二個文件中獲得行標識符匹配后,我需要用第二個文件的行替換第一個文件中的行。為此我使用SED如下。 但是Sed只替換了新文件中的那一行。 如何在沒有臨時文件的情況下在同一文件中實現更新(因為這些文件非常龐大)。

#!/bin/ksh
while read line
do
var=`echo $line|cut -c 3-25`
while read i
do
var1=`echo $i|cut -c 3-25`
if [ $var == $var1 ];
then
sed -i s/$line/$i/ t1
else

echo "not matched"
fi
done < t2
done < t1

即使沒有-i選項,我也沒有得到結果。 請幫我。

編輯 :或者建議我沒有臨時文件或任何腳本語言(不太喜歡)的任何其他最佳方式。

看看作為moreutils一部分的海綿

例如

% sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd

你不應該像這樣使用sed 正如您的腳本現在所說的那樣,它就是這樣說的:

  1. 對於t1中的每一行
  2. 逐步完成t2中的所有
  3. 如果t2中的一行與t1中的當前行匹配,則逐步執行t1中的所有行並替換匹配
  4. 轉到t1中的下一行並重復

這意味着每次從t1讀取一行時都會讀取整個t2文件。 這非常低效。

沒有必要使用echocut作為子串。 在Bash和ksh中你可以做到:

var=${line:3:23}

注意:cut使用字符開頭和結尾的字符位置,而此shell結構使用起始位置和字符數,因此您必須相應地調整數字。

如果t2是要在t1中進行替換的列表,那么t2是各種各樣的“腳本”,那么這可能會滿足您的需求:

keystart=3
keylen=23
while read line
do
    var="${line:$keystart:$keylen}"
    if (( ${#var} == keylen ))    # need "$" then don't need "$"
    then
        sed -in "/^.\{$keystart\}$var/ c$line" t1    # use double-quote so vars get expanded
    fi
done < t2

這將在t1中找到t2中每一行匹配並進行替換的所有行。

但是,如果t1和t2具有逐行對應關系並且您希望僅在相應行匹配的位置進行替換,則使用臨時文件進行替換將是最有效的:

tempfile=$(mktemp)
keystart=3
keylen=23
while read line1
do
    var1="${line1:$keystart:$keylen}"
    read line2 <&3    # use file descriptor 3 for input

    var2="${line2:$keystart:$keylen}"
    if [[ $var1 == $var2 && ${#var2} == $keylen ]]
    then
        echo "${line2}" >> $tempfile    # substitute when matched
    else
        echo "${line1}" >> $tempfile    # keep when not matched
    fi
done < t1 3< t2    # t1 is input on stdin, t2 is input on fd 3
mv t1 t1.bak && mv $tempfile t1

您不能將一條線替換為另一條線。 因為線條通常具有不同的長度並且將彼此重疊。 如果文件中的所有行都是相同的長度,那么它可以工作。 我還建議您使用更合適的語言來完成此任務(例如Perl),因為它在Shell中將是非常復雜的代碼。 我認為你應該尋找一個帶有臨時文件的解決方案,因為它更容易實現,並且可以輕松調試。 試想一下,如果你的龐大文件因腳本中的錯誤而被破壞,你會怎么做。

Sed設計用於管道 - 因此命名為“Stream EDitor”。 相反,您可以使用ex腳本來編輯文件。 Ex是vi最初基於行的文本編輯器(不像ed那樣老,舊的熊皮和石刀文本編輯器,但差不多)。 您可以根據自己的目的修改的簡單示例如下:

ex t1 << EOF
$lineNum
s/^.*$/$newline/
w
q
EOF

該腳本首先轉到$ lineNum指示的行,用$ newline的內容替換整行開頭(^)到end($),然后寫入並退出。 這些命令由“ <<EOF ”和“ EOF ”包圍,它們構成“here”文檔,基本上將腳本命令設置為stdin。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM