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

后端 未结 4 1557
无人及你
无人及你 2021-01-21 20:59

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

4条回答
  •  粉色の甜心
    2021-01-21 21:19

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

    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

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

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

    var=${line:3:23}
    

    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.

    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
    

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

    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
    

提交回复
热议问题