在谈到这个问题越来越线路识别符匹配在第一和第二个文件后,我需要,我使用SED如下第二file.For线替换第一个文件就行了。 但只用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
选项还我没有得到结果。 请帮我。
编辑 :要不给我建议没有临时文件或使用任何脚本语言(不太优选)做的任何其他最佳方式。
你不应该使用sed
这样。 当你的脚本现在站在这是这样说的:
- 对于t1每一行
- 通过T2的所有行步骤
- 如果在t2中的线路之一在T1当前行匹配,则通过在T1的所有行步骤和替换匹配
- 转到下一行t1和重复
这意味着,整个T2文件被读取每次一行被从t1读取。 这是令人难以置信的低效率。
这是没有必要使用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
这会发现在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
看看海绵这是一部分moreutils 。
如
% sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd
你可以不到位替换另一个一行。 因为线通常具有不同的长度,并且将彼此重叠。 如果你的文件中的所有行的长度相同,然后它可以工作。 我也建议你使用更合适的语言完成这个任务(如Perl为例),因为它会在壳牌进行非常复杂的代码。 我认为,你应该寻找颞文件的解决方案,因为它会更容易实现,它可以很容易地进行调试。 试想一下,你会怎么做,如果你巨大的文件将被currupted由于脚本错误。
SED被设计成流水线工作 - 因此得名“流编辑器”。 相反,你可以使用一个前的脚本编辑文件到位。 EX是在其第六最初基于基于行的文本编辑器(不一样古老版,旧熊皮和石刀文本编辑器,但几乎)。 一个简单的例子,你可以修改你的目的可能如下:
ex t1 << EOF
$lineNum
s/^.*$/$newline/
w
q
EOF
该脚本首先将变成由$ LINENUM指示的线路,替代以$换行的内容,整条生产线开始(^)结束($),然后写入和退出。 这些命令由“包围<<EOF
”和“ EOF
”,这些构成了“这里”的文件,基本上建立脚本命令作为标准输入。