我有两个文件;file1
包含 -
hello world
hello bangladesh
并file2
含有-
Dhaka in Bangladesh
Dhaka is capital of Bangladesh
我想更新file2
为 -
hello world
hello bangladesh
Dhaka in Bangladesh
Dhaka is capital of Bangladesh
这是由-完成的
cat file1 file2 >> file3
mv file3 file2
但是,我不想创建新文件。我想使用sed
它也许是可能的。
答案1
当然有可能。
(除非您还担心“在幕后”可能创建临时文件,因为几乎所有文本编辑器都是这样工作的。我并不是说完全不可能避免任何在幕后创建临时文件的可能性,但是这个答案没有涵盖它。)
printf '%s\n' '0r file1' x | ex file2
这是一个符合 POSIX 标准的命令,使用ex
,POSIX 指定的非视觉前身vi
。
printf
此处仅用于向编辑器提供命令。输出的内容printf
是:
0r file1
x
x
就是保存退出。
r
是“读入指定文件的内容”。
0
指定应在其后放置读入文本的行号。
答案2
使用标准工具就地修改文件的方法并不多。即使他们看起来这样做,他们也可能正在使用临时文件(即 GNU sed -i
)。
ex
另一方面,会做到这一点:
ex -n -c '0r file2' -c wq file1
ex
是一个行编辑器,并由vim
它演变而来,因此这些命令可能看起来很熟悉。与中的0r filename
操作相同:在给定地址(行号)之后插入指定的文件。这里的行号是 0,它是一种虚拟行,表示第 1 行之前的行。因此该文件将插入到任何现有文本之前。:0r filename
vim
然后我们wq
保存并退出。
如果您注意到下面有关此“非常脆弱”的评论,请持保留态度。如果您想在脚本中使用它,请务必执行适当的前置条件验证(文件存在、可读/可写等)。无论如何,好的编剧都会这么做。
更新:我添加了一些内容-n
来解决OP关于避免创建任何临时文件的担忧。假设您的实现是作为(就像大多数现代系统上的情况)ex
的一部分实现的,此标志将抑制正常的交换文件创建。vim
vim
答案3
all=$( cat file1 file2 )
echo "$all" > file2
仅适用于小文件。
答案4
与 Jasen 的答案类似,这是实用程序的基础。
代码海绵包装内更多实用程序旨在允许几乎任何程序(尽管是外部程序)就地功能。本质上,它吸收来自 STDIN 的输入,然后将收集的输出写入文件名,但不进行重定向。
我们喜欢这个想法,因此我们创建了一个类似的工作,可以在内存中收集数据,而不是像真正的海绵那样收集文件。
下面是一段 shell 脚本来说明这一点:
# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
pl " Input files data2, data3:"
head data[23]
pe
ls -gGli data[23]
pl " Results, re-write file from memory, preserving inode:"
cat data[23] | ./absorb-memory-public data3
head -v data3
pe
ls -gGli data3
生产:
-----
Input files data2, data3:
==> data2 <==
hello world
hello bangladesh
==> data3 <==
Dhaka in Bangladesh
Dhaka is capital of Bangladesh
1051395 -rw-r--r-- 1 30 Jan 7 08:58 data2
1052221 -rw-r--r-- 1 53 Jan 7 08:58 data3
-----
Results, re-write file from memory, preserving inode:
==> data3 <==
hello world
hello bangladesh
Dhaka in Bangladesh
Dhaka is capital of Bangladesh
1052221 -rw-r--r-- 1 83 Jan 7 08:58 data3
核心 Perl 代码非常短(特别是没有错误检查,添加错误检查可能是可取的):
use warnings;
use strict;
use Carp;
# Avoid hang for argument matching "-version","--version", etc.
exit(0) if @ARGV && $ARGV[0] =~ /-version/;
my ( $file, $f, $memory );
$file = shift || croak("Need a filename.");
$/ = 0777; # Slurp the entire STDIN
$memory = do { local $/; <> };
open( $f, ">", $file ) || die " Cannot open file \"$file\" for write.\n";
print $f "$memory";
在如下系统上运行:
OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution : Debian 8.9 (jessie)
bash GNU bash 4.3.30
perl 5.20.2
最美好的祝愿...干杯,drl