【问题标题】:Perl regex expressionPerl 正则表达式
【发布时间】:2012-07-22 01:22:40
【问题描述】:

我继承了一个从某些文件中提取数据的 perl 脚本。整个脚本运行良好,但最近一些工程师已经为某个通常取一个数字的位置输入了多个数字,因此输出并未显示所有预期的内容。

示例输入:

CRXXXX: "Then some text"

CRs XXXX, XXXX, XX, XXX

CRXXX "Some Text"

目前这个正则表达式语句我已经提取了 CR 之后的数字,但是如果给出第二行示例输入,它会打印 "s XXXX, XXXX, XX, XXX" 而不是想要的 "XXXX XXXX XX XXX"

我对 perl 非常陌生,并且正在努力弄清楚如何更改此正则表达式以处理所有输入。

 $temp_comment =~ s/\s[cC][rR][-\s:;]*([\d])/\n$1/mg;

提前致谢!

布洛克

【问题讨论】:

  • 这个很不清楚。您不能给我们一些真实数据和您想要的相应输出吗? X 字符应该是数字吗?
  • Brock,另外两行输入的预期输出是多少?您的正则表达式应该匹配 CRXXX 部分还是后面的“某些文本”?
  • 你想要什么输出?
  • 是的,X 是数字,很抱歉忘记提及这一点。其他行的预期输出只是“CR”后面的数字,例如,如果 CR1234:“blah blah blah”,它将更改为 1234。或者如果 CR999“随机文本”只是更改为 999

标签: regex perl parsing scripting


【解决方案1】:

对于示例数据,例如:

my $temp_comment =
'CR1234: "Then some text"
 CRs 2345, 3456, 45, 567
 CR678 "Some Text"';

尝试:

$temp_comment =~ s/(,)|[^\d\n]+/$1?' ':''/semg;

或者,如果您想靠近字符串模板:

$temp_comment =~ s/ ^                 # multi-line mode, line start
                    \s*               # leading blanks?
                    CR                # CR tag
                    \D*               # non-number stuff
                     (                  # start capture group
                      (?:\d+ [,\s]*)+   # find (number, comma, space) groups
                     )                  # end capture group
                    \D*               # skip remaining non-number stuff
                    $                 # multi-line mode, line end
                  /$1/mxg;            # set multi-line mode + regex comments "x" 

但您必须在后续步骤中删除数字组中的逗号。

$temp_comment =~ tr/,//d;             # remove commas in the whole string

或

$temp_comment =~ s/(?<=\d),(?=\s\d)//g;  # remove commas between numbers '11, 22'

对于“单步”,您必须使用/e 修饰符:

$temp_comment =~ s{ ^                 # line start
                    \s*               # leading blanks?
                    CR                # CR tag
                    \D*               # non-number stuff
                    ((?:\d+ [,\s]*)+) # single or group of numbers
                    \D*               # non number stuff
                    $                 # line end
                  }
                  {do{(local$_=$1)=~y/,//d;$_}}mxeg;

根据上面的数据,这将导致:

1234
2345 3456 45 567
678 

但真的,请使用,如果可能的话,更简单的两步法。后一种正则表达式可能是您的继任者的维护噩梦。

【讨论】:

  • 我需要它来分隔输入中分组的每组数字。例如 CR1234, 111, 333, 3453, 55555 理想情况下会变成“1234 111 333 3453 55555”甚至这个 1234 \n 111 \n 333 \n 3453 \n 55555
  • 究竟如何看待您的输入数据?你有单行吗?还是行之间带有换行符\n 的$ 变量(如我的帖子中所示)?输入 dat 的输出究竟如何?换行符呢?
  • 数据行之间的新行。就像你上面的一样。而你输入的第二个工作或至少更好,我想我只需要把逗号变成换行符
  • 感谢您的帮助,我使用了您的第二个想法,然后又做了一行将逗号更改为换行符。
  • 你能像上一个一样把 cmets 放进去解释你在那个中的步骤吗?有些部分还是有点过头了
【解决方案2】:

您最好分两步进行:

1) 创建你的正则表达式

s/\s[cC][rR][-\s:;]*([\d\ ]+)/\n$1/mg(注意捕获所有数字的新方法,您只捕获上面的第一个数字)

2) 然后用 find/replace 去掉字符串中的逗号。

【讨论】:

    【解决方案3】:
    my ($v) = /CR[s ]*((?:\d+[\s,]*)*)/ig;
    $v =~ s/,//g;
    print $v,"\n";
    

    【讨论】:

    • 对于 perl 新手(OP),您可能应该添加表达式的上下文 ($_) 并指出原始 替换 和您的 匹配.
    【解决方案4】:

    也许以下方法对你有用:

    use Modern::Perl;
    
    say join ' ', (/(\d+)/g) for <DATA>;
    
    __DATA__
    CR1234: "Then some text"
    CRs 1111, 2222, 33, 444
    CR567 "Some Text"
    

    输出:

    1234
    1111 2222 33 444
    567
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多