Regex perl多行查找和替换
我尝试在以下输入上使用简单的perl one liner:Regex perl多行查找和替换,regex,perl,sed,awk,multiline,Regex,Perl,Sed,Awk,Multiline,我尝试在以下输入上使用简单的perl one liner: @F7##########0/1 C4CTA6GCAAC56G67CTCA99C + b[[WZ56W]87X9HBB @44FC6%%%%&&&&&&&1UP1 GTS4HY2IOMD3FCCA8DFLLLTG + ]]^4YY23ZV\6`a8`^9^a 等等 我希望我的输出看起来像: @F7##########0/1 C4CTA6GCAAC56G67CTCA99C +F7#
@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
之后的任何内容
当然,有一个工作班轮在那里完成这一点
Awk
或Sed
或tr
一行程序是受欢迎的,但是对file.txt
的更改必须在线进行,因为file.txt
很大,不希望写入另一个文件。下面的程序似乎可以满足您的需要
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;
下面的程序似乎可以满足您的需要
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;
不幸的是,
awk
不提供在线更改,因此它可能不是您所需要的。但是如果你这样做了,那么下面的方法就行了-
awk '/^@/{a=substr($0,2)}/^\+/{printf ("%s%s\n", $0,a);next}1' file > newfile
更新:我已尝试执行您在sed
中希望执行的操作,该操作允许对文件中的进行更改
sed -i '/^@/{h};/^\+/{x;s/\(.\)\(.*\)/+\2/}' file
说明:
/^@/{h}
:我们寻找以@
符号开头的行,当我们找到它时,我们将整行放入保留空间中Sed
有两个缓冲区,模式空间
和保持空间
<代码>模式空间
是所有操作发生的地方<代码>保留空间
允许我们暂时保留信息,以便稍后对其执行某些操作李>
/^\+/{x;…
:当我们找到一行以+
开头时,我们对它执行x
操作。它的意思是,我们从保留空间中提取信息,然后将其放回模式空间中。一旦我们这样做了,我们就做了一个简单的替换
…s/\(.\)\(.*\)/+\2/
:这意味着我们使用分组
来识别字符。因为我们的文本部分前面有@
,这是您不想要的,所以我们使用
来隔离该字符,这意味着任何字符。我们还将该行的所有其他内容放在第二个组中。这些组需要转义{所以你看到的是\(\)而不是()}。在替换部分,我们放入了一个+
和第二个组。记住,捕获的第一个组中只有@
。我们只需要第二个组,所以我们使用\2
引用它(反斜杠和您希望引用的组数)awk
:
测试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
不幸的是,
awk
不提供在线更改,因此它可能不是您所需要的-
awk '/^@/{a=substr($0,2)}/^\+/{printf ("%s%s\n", $0,a);next}1' file > newfile
更新:我已尝试执行您在sed
中希望执行的操作,该操作允许对文件中的进行更改
sed -i '/^@/{h};/^\+/{x;s/\(.\)\(.*\)/+\2/}' file
说明:
/^@/{h}
:我们寻找以@
符号开头的行,当我们找到它时,我们将整行放入保留空间Sed
有两个缓冲区,模式空间和保留空间模式空间是所有操作发生的地方。保留空间允许我们保留信息暂时停止,以便我们以后可以对其采取一些行动
/^\+/{x;…
:当我们找到一行以+
开头时,我们对它执行x
操作。它的意思是,我们从保留空间中提取信息,然后将其放回模式空间中。一旦我们这样做了,我们就做了一个简单的替换
…s/\(.\)\(.*\)/+\2/
:这意味着我们使用分组
来识别字符。因为我们的文本部分前面有@
,这是您不想要的,所以我们使用
来隔离该字符,这意味着任何字符。我们还将该行的所有其他内容放在第二个组中。这些组需要转义{所以你看到的是\(\)而不是()}。在替换部分,我们放入了一个+
和第二个组。记住,捕获的第一个组中只有@
。我们只需要第二个组,所以我们使用\2
引用它(反斜杠和您希望引用的组数)
测试awk
:
测试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
我很抱歉。我更仔细地阅读了你的问题,发现你想一行一行地处理你的文件。这一行就可以做到这一点
perl -pe "$dat = $1 if /^\@(.+)/; s/^\+/+$dat/;" infile
我很抱歉。我更仔细地阅读了你的问题,发现你想一行一行地处理你的文件。这一行就可以做到这一点
perl -pe "$dat = $1 if /^\@(.+)/; s/^\+/+$dat/;" infile
这可能适合您:
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
这可能适合您:
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
当我尝试使用sed
时,那行sed
正是我最初想要的。然而,当我无法匹配或替换\n
时,我放弃了sed
。它看起来像复杂的正则表达式,你介意为我解释一下吗?那真的很好!一个A+解释。谢谢!做得好。在sed解决方案中在/^\+/
上,我被抛出了一会儿,因为没有-r
开关+
不是特殊的,通常不需要转义。但是,如果转义,它意味着前面的字符或子表达式中有一个或多个
,但是在反常的逻辑中,^
是位置标记,而不是一个字符,它会还原为一个字符<