如何在Unix Shell脚本中通过SED替换同一文件中的行? [英] How to Replace a line in the same file by SED in Unix Shell scripting?

查看:199
本文介绍了如何在Unix Shell脚本中通过SED替换同一文件中的行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参考此问题第一个和第二个文件中的标识符匹配我需要用第二个文件的行替换第一个文件中的行.为此,我正在使用SED,如下所示.但是Sed仅在新文件中替换该行.如何在没有临时文件的情况下在同一文件中完成更新(因为这些文件非常大).

In Reference to this question After getting the line identifier matching in first and second file I need to replace the line in first file with the line of second file.For that I am using SED as below. But Sed only replaces that line in a new file. How can I achieve the update in same file without temporary file (Because those are very huge files).

#!/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选项,我也没有得到结果.请帮助我.

Even without -i option also I am not getting the result. Please help me.

编辑:或者向我建议其他没有临时文件或任何脚本语言(较不推荐)的最佳方式.

Edit: Or else suggest me any other optimal way of doing without temporary files or with any scripting languages(less preferred).

推荐答案

您不应该这样使用sed.正如您的脚本现在所说的那样:

You shouldn't use sed like that. As your script now stands this is what it says:

  1. 对于t1中的每一行
  2. 逐步完成所有 t2中的行
  3. 如果t2中的一行与t1中的当前行匹配,则逐步浏览 t1中的所有行并替换匹配项
  4. 转到t1中的下一行并重复
  1. For each line in t1
  2. Step through all the lines in t2
  3. If one of the lines in t2 matches the current line in t1, then step through all the lines in t1 and replace the matches
  4. Go to the next line in t1 and repeat

这意味着每次从t1读取一行都读取整个t2文件.这是非常低效的.

That means that the entire t2 file is read each time one line is read from t1. This is incredibly inefficient.

对于子字符串,不必使用echocut.在Bash和ksh中,您可以执行以下操作:

It's not necessary to use echo and cut for substrings. In Bash and ksh you can do:

var=${line:3:23}

注意:cut使用字符位置作为范围的开始和结束,而此shell构造使用起始位置和字符数,因此您必须相应地调整数字.

Note: cut uses character positions for the beginning and end of a range, while this shell construct uses starting position and character count so you have to adjust the numbers accordingly.

如果t2是要在t1中进行的替换的列表,那么t2是某种脚本",那么这可能会满足您的要求:

If t2 is a list of replacements to be made in t1, thus t2 is a "script" of sorts, then this might do what you need:

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中的每一行匹配的 all 行,并进行替换.

This will find all the lines in t1 that each line in t2 matches and do the replacement.

但是,如果t1和t2具有逐行对应关系,并且您只想在对应行匹配的地方进行替换,那么使用临时文件,这将是最有效的:

If, however, t1 and t2 have a line-for-line correspondence and you want to make the substitution only where corresponding lines match, then this, using a temporary file, will be the most efficient:

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

这篇关于如何在Unix Shell脚本中通过SED替换同一文件中的行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆