我想将符合某些模式的行从 file1 移动到 file2 。类似于操作在Windows中将文件从一个文件剪切并粘贴到另一个
示例
假设我想从 file1 中删除所有包含bar
的行,并将其粘贴到新创建的 file2
输入:
文件1
bla foo bla
bla bar bla
bla aaa bla
bla bar bla
bla foo bla
处理后的所需输出:
文件1
bla foo bla
bla aaa bla
bla foo bla
file2的
bla bar bla
bla bar bla
我尝试了什么
grep
创建所需的 file2 但不修改 file1
grep 'bar' file1 > file2
sed -i
修改了所需的 file1 ,但未创建 file2
sed -i '/bar/d' file1
如果我一个接一个地执行这两个命令,我得到了理想的结果。但在这里,我出于好奇心寻找单行命令,并使脚本更简洁。
我们将不胜感激。
答案 0 :(得分:16)
这可能适合你(GNU sed):
sed -i -e '/bar/{w file2' -e 'd}' file1
替代方案:
sed -i -e '/bar/w file2' -e '//d' file1
要附加到file2,请写入临时文件并使用cat在bash脚本中附加到文件末尾,或使用:
sed -i -e '/bar/w tmpfile' -e '$e cat tmpfile >> file2 && rm tmpfile' -e '//d' file1
N.B。对于最后一个解决方案,一次只能修改一个输入文件。
答案 1 :(得分:5)
您可以使用perl并在打印时根据正则表达式的匹配选择不同的文件句柄:
perl -i.bak -ne 'BEGIN { open $oh, q|>|, pop or die } { print { m/bar/ ? $oh : q|ARGVOUT| } $_ }' file1 file2
它产生:
==> file1 <==
bla foo bla
bla aaa bla
bla foo bla
==> file2 <==
bla bar bla
bla bar bla
答案 2 :(得分:3)
这个awk
脚本可以解决这个问题:
awk '{a[NR]=$0}END{for(i=1;i<=NR;i++)print a[i] > "file"(a[i]~/bar/?2:1)}' file1
输出:
$ cat file1
bla foo bla
bla aaa bla
bla foo bla
$ cat file2
bla bar bla
bla bar bla
答案 3 :(得分:1)
您可以在两个命令之间放置&&
以使它们成为一行。但那不会更具可读性,所以我不建议你这样做。
要在一个命令中执行相同的操作,您需要一些可以就地编辑文件的内容,删除您不想要的行,同时将这些行打印到stdout
或{{1}所以你可以将它重定向到另一个文件。
也许stderr
可以做到这一点,但我不知道如何写。
我认为没有其他“标准”UNIX工具可以做到这一点。
Btw, cut&amp;粘贴实际上有3个步骤:
两步UNIX命令不使用剪贴板。
答案 4 :(得分:0)
我喜欢其他答案,但只是一种(显而易见的)替代方法,以防您担心在模式中出错并希望以简单的方式回滚:
grep 'bar' file1 > file2
grep -v 'bar' file1 > file3
一旦您对结果感到满意(提示:tee
而非>
将允许您查看您的文件被写入的内容):
mv file3 file1
一般来说,我更喜欢perl做上面回答中的替换,但是当正则表达式变得过于复杂并且你半盲目地复制和粘贴你不理解的命令时,你就无法控制您珍贵的数据。