perl multiline查找和替换

时间:2012-01-20 02:37:45

标签: regex perl sed awk multiline

我试图在以下输入中使用简单的perl单行程序:

@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+
]]^4YY23ZV\6`a8`^9^a

我希望我的输出看起来像:

@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a

我想搜索以@开头的行,并在$1中存储(分组)该行的其余部分。然后,我找到下一个+,并在该行的末尾添加$1

我已尝试perl -pi -e "s%^@(.*)$\1\n(.*)$\2\n(\+)$\3\n%$1\n$2\n\+$1%mg" file.txt但我似乎无法在^@(.*)$\1\n之后匹配任何内容。

当然,那里有一个工作的单行程来实现这一目标。我们欢迎AwkSedtr个单行,但file.txt的更改必须符合要求,因为file.txt很大并且写入另一个文件是不受欢迎的。

4 个答案:

答案 0 :(得分:3)

不幸的是awk不提供内联更改,因此可能不是您需要的内容。但如果你这样做,那么下面的工作就可以了 -

awk '/^@/{a=substr($0,2)}/^\+/{printf ("%s%s\n", $0,a);next}1' file > newfile

更新:我已尝试在 sed 中执行您要查找的内容,以便进行in-file更改。

sed -i '/^@/{h};/^\+/{x;s/\(.\)\(.*\)/+\2/}' file

说明:

  • /^@/{h} :我们查找以@符号开头的行,当我们找到它时,我们将整行放在hold space中。 Sed有两个缓冲区,pattern spacehold spacePattern space是所有行动发生的地方。 hold space允许我们暂时保留信息,以便我们以后可以对其执行某些操作。
  • /^\+/{x;... :当我们找到以+开头的行时,我们会对其执行x操作。这意味着,我们从hold space中提取信息并将其放回pattern space。一旦我们完成了这个,我们就做了一个简单的替换。
  • ...s/\(.\)\(.*\)/+\2/ :这意味着我们使用grouping识别字符。由于我们的部分文本前面有@,你不想要,我们使用.来表示任何字符。我们还将该行的其他所有内容放在第二组中。这些组需要进行转义{所以你看到\(\)而不是just()}。在替换部分,我们放入+和第二组。请记住,第一个捕获的群组中只有@。我们只想要第二组,因此我们使用\2(反斜杠和您想要引用的组的数量)来引用它。

测试awk

[jaypal:~/Temp] cat file
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+
]]^4YY23ZV\6`a8`^9^a

[jaypal:~/Temp] awk '/^@/{a=substr($0,2)}/^\+/{printf ("%s%s\n", $0,a);next}1' file
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a

测试sed

您可以使用-i选项进行更改。以下仅用于演示,以便您可以看到输出。

[jaypal:~/Temp] sed '/^@/{h};/^\+/{x;s/\(.\)\(.*\)/+\2/}' file
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a

答案 1 :(得分:2)

道歉。我更仔细地阅读了您的问题,并确定您要逐行处理您的文件。这个单线将实现那个

perl -pe "$dat = $1 if /^\@(.+)/; s/^\+/+$dat/;" infile

答案 2 :(得分:0)

以下程序似乎可以满足您的需求

use strict;
use warnings;

my $str = <<'STR';
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+
]]^4YY23ZV\6`a8`^9^a
STR

$str =~ s/^@(.+?)$(.+?)^\+/\@$1$2+$1/gms;

print $str;

<强>输出

@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a

答案 3 :(得分:0)

这可能对您有用:

sed '/^@/h;/^+/{G;s/\n@//}' file
@F7##########0/1
C4CTA6GCAAC56G67CTCA99C
+F7##########0/1
b[[WZ56W]87X9HBB
@44FC6%%%%&&&&&&&1UP1
GTS4HY2IOMD3FCCA8DFLLLTG
+44FC6%%%%&&&&&&&1UP1
]]^4YY23ZV\6`a8`^9^a