在Unix Shell脚本中,如何用SED替换同一文件中的一行?
在获得第一个和第二个文件中匹配的行标识符之后,我需要用第二个文件的行替换第一个文件中的行。但是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 完成
#/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。你的剧本现在是这样写的:
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