将匹配模式的行从一个文件移动到另一个文件

时间:2013-10-19 10:41:13

标签: linux perl sed awk grep

我想将符合某些模式的行从 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

如果我一个接一个地执行这两个命令,我得到了理想的结果。但在这里,我出于好奇心寻找单行命令,并使脚本更简洁。

我们将不胜感激。

5 个答案:

答案 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 -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个步骤:

  1. 将所选文本复制到剪贴板
  2. 从原始文件中删除
  3. 从剪贴板粘贴到新文件
  4. 两步UNIX命令不使用剪贴板。

答案 4 :(得分:0)

我喜欢其他答案,但只是一种(显而易见的)替代方法,以防您担心在模式中出错并希望以简单的方式回滚:

grep    'bar' file1 > file2
grep -v 'bar' file1 > file3

一旦您对结果感到满意(提示:tee而非>将允许您查看您的文件被写入的内容):

mv file3 file1

一般来说,我更喜欢perl做上面回答中的替换,但是当正则表达式变得过于复杂并且你半盲目地复制和粘贴你不理解的命令时,你就无法控制您珍贵的数据。