我在文件中有一个如下图案,它可以/不能跨越多行:
abcd25
ef_gh
( fg*_h
hj_b*
hj ) {
我尝试过:
perl -nle'打印时m / ^ \ s *(\ w +)\ s +(\ w +?)\ s *(([\ w-0-9,* \ s] ))\ s {/克'
我不知道这里的标志是什么意思,但我所做的只是为模式写一个regex
并将其插入模式空间。如果模式在一行中,则匹配良好:
abcd25 ef_gh ( fg*_h hj_b* hj ) {
但是在多线情况下完全失败了!
我昨天开始使用perl,但语法太混乱了。所以,正如我们的SO伙伴之一所建议的那样,我写了一个regex
并将其插入到他提供的代码中。
我希望perl
僧侣可以在这种情况下帮助我。欢迎替代解决方案。
输入文件:
abcd25
ef_gh
( fg*_h
hj_b*
hj ) {
abcd25
ef_gh
fg*_h
hj_b*
hj ) {
jhijdsiokdù ()lmolmlxjk;
abcd25 ef_gh ( fg*_h hj_b* hj ) {
预期产出:
abcd25
ef_gh
( fg*_h
hj_b*
hj ) {
abcd25 ef_gh ( fg*_h hj_b* hj ) {
输入文件可以有多个模式,这些模式与所需模式的开始和结束模式一致。 提前感谢您的回复。
答案 0 :(得分:6)
Perl使用触发器操作员非常容易,这将允许您打印出两个正则表达式之间的所有行。例如:
$ perl -ne 'print if /^abcd25/ ... /\bhj \) {/' /tmp/foo
abcd25
ef_gh
( fg*_h
hj_b*
hj ) {
然而,像这样的简单单行将不会区分您想要拒绝分隔模式之间的特定匹配的匹配。这需要更复杂的方法。
单行并不总是最佳选择,如果正则表达式过于复杂,它们可能会很快失控。在这种情况下,你最好编写一个可以使用条件分支的实际程序,而不是尝试使用过于聪明的正则表达式匹配。
执行此操作的一种方法是使用简单模式构建匹配项,然后拒绝任何与某些其他简单模式不匹配的匹配项。例如:
#!/usr/bin/perl -nw
# Use flip-flop operator to select matches.
if (/^abcd25/ ... /\bhj \) {/) {
push @string, $_
};
# Reject multi-line patterns that don't include a particular expression
# between flip-flop delimiters. For example, "( fg" will match, while
# "^fg" won't.
if (/\bhj \) {/) {
$string = join("", @string);
undef @string;
push(@matches, $string) if $string =~ /\( fg/;
};
END {print @matches}
当针对OP的更新语料库运行时,这正确地产生:
abcd25
ef_gh
( fg*_h
hj_b*
hj ) {
abcd25 ef_gh ( fg*_h hj_b* hj ) {
答案 1 :(得分:5)
正则表达式甚至不匹配单行。你认为双括号怎么办?
你可能想要
m/^\s*(\w+)\s+(\w+?)\s*\([\w0-9,*\s]+\)\s{/gm
更新:规格已更改。正则表达式(几乎)没有,但你必须稍微改变代码:
perl -0777 -nle 'print "$1\n" while m/^\s*(\w+\s+\w+?\s*\([\w0-9,*\s]+\)\s{)/gm'
另一次更新:
说明:
perlrun
:zero,n,l,e 正则表达式可由YAPE::Regex::Explain
自动解释perl -MYAPE::Regex::Explain -e 'print YAPE::Regex::Explain->new(qr/^\s*(\w+\s+\w+?\s*\([\w0-9,*\s]+\)\s{)/)->explain'
The regular expression:
(?-imsx:^\s*(\w+\s+\w+?\s*\([\w0-9,*\s]+\)\s{))
matches as follows:
NODE EXPLANATION
----------------------------------------------------------------------
(?-imsx: group, but do not capture (case-sensitive)
(with ^ and $ matching normally) (with . not
matching \n) (matching whitespace and #
normally):
----------------------------------------------------------------------
^ the beginning of the string
----------------------------------------------------------------------
\s* whitespace (\n, \r, \t, \f, and " ") (0 or
more times (matching the most amount
possible))
----------------------------------------------------------------------
( group and capture to \1:
----------------------------------------------------------------------
\w+ word characters (a-z, A-Z, 0-9, _) (1 or
more times (matching the most amount
possible))
----------------------------------------------------------------------
\s+ whitespace (\n, \r, \t, \f, and " ") (1
or more times (matching the most amount
possible))
----------------------------------------------------------------------
\w+? word characters (a-z, A-Z, 0-9, _) (1 or
more times (matching the least amount
possible))
----------------------------------------------------------------------
\s* whitespace (\n, \r, \t, \f, and " ") (0
or more times (matching the most amount
possible))
----------------------------------------------------------------------
\( '('
----------------------------------------------------------------------
[\w0-9,*\s]+ any character of: word characters (a-z,
A-Z, 0-9, _), '0' to '9', ',', '*',
whitespace (\n, \r, \t, \f, and " ") (1
or more times (matching the most amount
possible))
----------------------------------------------------------------------
\) ')'
----------------------------------------------------------------------
\s whitespace (\n, \r, \t, \f, and " ")
----------------------------------------------------------------------
{ '{'
----------------------------------------------------------------------
) end of \1
----------------------------------------------------------------------
) end of grouping
----------------------------------------------------------------------