Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Unix Shell脚本中,如何用SED替换同一文件中的一行?_Unix_File_Shell_Replace_Sed - Fatal编程技术网

在Unix Shell脚本中,如何用SED替换同一文件中的一行?

在Unix Shell脚本中,如何用SED替换同一文件中的一行?,unix,file,shell,replace,sed,Unix,File,Shell,Replace,Sed,在获得第一个和第二个文件中匹配的行标识符之后,我需要用第二个文件的行替换第一个文件中的行。但是Sed只在新文件中替换该行。如何在没有临时文件的情况下在同一个文件中实现更新(因为这些文件非常大) #/bin/ksh 读行时 做 var=`echo$line | cut-c3-25` 当我读书的时候 做 var1=`echo$i | cut-c3-25` 如果[$var==$var1]; 然后 sed-is/$line/$i/t1 其他的 回声“不匹配” fi 完成

在获得第一个和第二个文件中匹配的行标识符之后,我需要用第二个文件的行替换第一个文件中的行。但是Sed只在新文件中替换该行。如何在没有临时文件的情况下在同一个文件中实现更新(因为这些文件非常大)

#/bin/ksh
读行时
做
var=`echo$line | cut-c3-25`
当我读书的时候
做
var1=`echo$i | cut-c3-25`
如果[$var==$var1];
然后
sed-is/$line/$i/t1
其他的
回声“不匹配”
fi
完成
即使没有
-i
选项,我也不会得到结果。请帮帮我


编辑:或者向我推荐任何其他不使用临时文件或任何脚本语言的最佳方法(不太可取)。

您不能用一行替换另一行。因为直线通常有不同的长度,并且会相互重叠。如果文件中的所有行的长度相同,那么它就可以工作。我还建议您为这个任务使用更合适的语言(例如Perl),因为在Shell中它将是非常复杂的代码。
我认为您应该寻找一个使用时态文件的解决方案,因为它更容易实现,并且可以轻松调试。想象一下,如果由于脚本中的错误,您的大文件将被刷新,您会怎么做。

看看作为脚本一部分的海绵

e、 g


你不应该那样使用sed。你的剧本现在是这样写的:

  • 对于t1中的每一行
  • 逐步通过t2中的所有行
  • 如果t2中的一行与t1中的当前行匹配,则单步执行t1中的所有行并替换匹配项
  • 转到t1中的下一行并重复
  • 这意味着每次从t1读取一行时,都会读取整个t2文件。这是难以置信的低效

    子字符串不必使用
    echo
    cut
    。在Bash和ksh中,您可以执行以下操作:

    var=${line:3:23}
    
    注意:剪切使用字符位置作为范围的开始和结束,而此外壳结构使用开始位置和字符计数,因此您必须相应地调整数字

    如果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
    
    keystart=3
    凯伦=23
    读行时
    做
    var=“${line:$keystart:$keylen}”
    如果(${var}==keylen))#需要“$”则不需要“$”
    然后
    sed-in“/^.\{$keystart\}$var/c$line”t1#使用双引号以便扩展变量
    fi
    完成
    这将找到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
    
    tempfile=$(mktemp)
    keystart=3
    凯伦=23
    读第1行时
    做
    var1=“${line1:$keystart:$keylen}”
    读取第2行>$tempfile#匹配时替换
    其他的
    回显“${line1}”>$tempfile#不匹配时保留
    fi
    完成
    Sed设计为在管道中工作-因此得名为“流编辑器”。相反,您可以使用ex脚本就地编辑文件。Ex是vi最初基于的基于行的文本编辑器(不像ed、旧的熊皮和石头刀文本编辑器那样古老,但几乎是如此)。您可以根据自己的目的修改的简单示例如下:

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

    ext1如果你能显示你的输入文件,并描述你的最终输出,这是最好的。你说的“巨大”是什么意思?除非每个文件占用您文件系统的45%,并且您没有其他文件系统可供使用,否则临时文件是最好的选择。如果文件这么大,那么考虑购买一个更大的磁盘。仓库很便宜,谢谢你。我正在调查此事。
    
    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
    
    ex t1 << EOF
    $lineNum
    s/^.*$/$newline/
    w
    q
    EOF