Answers:
你不能 使用ed或GNU sed或perl,或在后台进行操作,即为内容创建一个新文件。
ed
,便携式:
ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/
w
q
EOF
GNU sed
:
sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/' foo
Perl:
perl -i -l -F, -pae 'print @F[1,3]' foo
cut
,创建一个新文件(建议,因为如果脚本被中断,则可以再次运行它):
cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo
cut
,就地替换文件(保留的所有权和权限foo
,但需要保护以防中断):
cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old
我建议使用cut
基于-的方法之一。这样,您就不必依赖任何非标准工具,可以使用最佳工具来完成工作,并且可以控制中断时的行为。
cut -d , -f 1,3 foo > foo.new
rm foo
mv foo.new foo
rm foo
。而且您不应该调用rm foo
,因为mv foo.new foo
它是原子的:它将删除旧版本,同时将新版本放置到位。
好吧,由于cut
产生的输出少于读取的输出,因此您可以执行以下操作:
cut -c1 < file 1<> file
也就是说,将其stdin file
在只读模式下file
打开,并将其stdout 在读+写模式下打开,而不用截断(<>
)。
这样,cut
只会覆盖文件本身。但是,它将保留文件的其余部分不变。例如,如果file
包含:
foo
bar
输出将变为:
f
b
bar
在f\nb\n
已经更换foo\n
,但bar
仍然存在。完成后,您需要截断文件cut
。
使用ksh93
,您可以使用其<>;
运算符来执行此操作,该运算符的行为类似于在文件描述符上调用<>
的命令是否成功ftruncate()
。所以:
cut -c1 < file 1<>; file
对于其他shell,您需要ftruncate()
通过其他一些方式来进行操作,例如:
{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file
尽管perl
为此专门调用是有点矫kill过正,尤其是考虑到perl
可以轻松完成以下cut
任务:
perl -pi -e '$_ = substr($_, 0, 1)' file
请注意,对于所有涉及实际就地重写的方法,如果操作在中途中断,最终将导致文件损坏。使用第二个临时文件可以避免此问题。
.old
就地更改的方法更好,echo "$(cut -d , -f 1,3 <foo)" > foo