我有file1
,并且我需要删除与模式匹配的行。但我想将这些删除的行保存在另一个file2
.
sed '/zz/!d' file1 > file2
sed -i '/zz/d' file1
有没有办法将这些命令合并为一个?
或者有更优雅的方法吗?
答案1
在 GNU Sed 上检查:
sed -ni '/zz/!{p;b};w file2' file1
标志必须按该顺序排列-ni
。
说明:我们不使用命令停止脚本d
,而是设置标志(静默)并使用命令(打印当前模式空间)-n
写入与模板不匹配的行,然后跳转到脚本末尾。与模式匹配的行到达命令,该命令将模式空间写入文件。p
b
w
答案2
perl -pi -e 'select( /zz/ ? STDOUT : ARGVOUT )' file1 > file2
-i
处理 file1 的就地编辑。-p
运行 perl 程序后打印行。程序需要做的就是选择输出的位置。在这种情况下,可以使用?:
选择标准输出或ARGVOUT
(这就是-i
使用的)来实现。
答案3
对于任何 Awk:
awk '/zz/{print >> "file2"; next} 1' file1 > tmp && mv tmp file1
如果您不喜欢显式创建临时文件,请使用GNU awk:
gawk -i inplace '/zz/{print >> "file2"; next} 1' file1
如果您想截断而不是追加,请更改>>
为。>
file2
也可以看看:为什么 awk 中的“1”打印当前行?
答案4
perl
只需与该标志一起使用-i
,并将匹配的行打印到标准输出,以便您可以将它们重定向到文件:
$ cat file1
asdasd
baba zzbabab
asdasd
sadkzzpasdad
$ perl -i -ne 'if(/zz/){ print STDOUT } else{ print }' file1 > file2
You could rewrite the above via a string form of eval where we construct
the above piece of perl code based on presence of zz:
$ perl -i -ne 'eval "print ".qw[STDOUT][!/zz/]' file1 > file2
$ cat file1
asdasd
asdasd
$ cat file2
baba zzbabab
sadkzzpasdad
Perl 中的另一种方法可以是:
$ perl -pi -e 'print(STDOUT),s/.*//s if /zz/' file1 > file2
- 使用自动打印模式
-p
- 将 zz 行打印到标准输出中,然后当它们通过模式写回到文件 1 时将它们清空
-i
。