如何在Perl中的字符串中包含新行?

时间:2015-06-05 11:07:26

标签: string perl newline

我有一个看起来像这样的字符串

Acanthocolla_cruciata,#8B5F65Acanthocyrta_haeckeli,#8B5F65Acanthometra_fusca,#8B5F65Acanthopeltis_japonica,#FFB5C5

我想添加新行,所以进入列表格式。喜欢这个

Acanthocolla_cruciata,#8B5F65
Acanthocyrta_haeckeli,#8B5F65
Acanthometra_fusca,#8B5F65
Acanthopeltis_japonica,#FFB5C5

我有一个perl脚本

use strict;
use warnings;

open my $new_tree_fh, '>', 'test_match.txt'
  or die qq{Failed to open "update_color.txt" for output: $!\n};
open my $file,  '<', $ARGV[0]
  or die qq{Failed to open "$ARGV[0]" for input: $!\n};

while ( my $string = <$file> ) {
    my $splitmessage = join ("\n", ($string =~ m/(.+)+\,+\#+\w{6}/gs));

    print $new_tree_fh $splitmessage, "\n";
}

close $file;
close $new_tree_fh;

模式匹配有效但不会打印新行,因为我想制作列表。任何人都可以提出任何建议。

3 个答案:

答案 0 :(得分:1)

好的,我认为你的问题是你的正则表达式没有正确匹配。

(.+)+
例如

- 可能没有做你认为它做的事情。它贪婪地捕获了一个或多个&#34;任何东西&#34;这将抓住你的整个字符串。

regex101上查看。

尝试:

#!/usr/bin/perl

use strict;
use warnings;
while ( my $string = <DATA> ) {
    my $splitmessage = join( "\n", ( $string =~ m/(\w+,\#+\w{6})/g ) );
    print $splitmessage, "\n";
}

__DATA__
Acanthocolla_cruciata,#8B5F65Acanthocyrta_haeckeli,#8B5F65Acanthometra_fusca,#8B5F65Acanthopeltis_japonica,#FFB5C5

将打印:

Acanthocolla_cruciata,#8B5F65
Acanthocyrta_haeckeli,#8B5F65
Acanthometra_fusca,#8B5F65
Acanthopeltis_japonica,#FFB5C5

答案 1 :(得分:1)

我会这样做:

my $str = 'Acanthocolla_cruciata,#8B5F65Acanthocyrta_haeckeli,#8B5F65Acanthometra_fusca,#8B5F65Acanthopeltis_japonica,#FFB5C5';
$str =~ s/(?<=,#\w{6})/\n/g;
say $str;

<强>输出:

Acanthocolla_cruciata,#8B5F65
Acanthocyrta_haeckeli,#8B5F65
Acanthometra_fusca,#8B5F65
Acanthopeltis_japonica,#FFB5C5

答案 2 :(得分:1)

让我们在现有代码中找到问题,而不是快速修复解决方案。您的问题在正则表达式中,因此我们将解剖并修复它。

($string =~ m/(.+)+\,+\#+\w{6}/gs)
  • 首先,导致该错误的两个重大错误:

    1. 一开始,您正在进行.+,然后与,#进行匹配,依此类推。问题是,.+是贪婪的,这意味着它会与输入中的最后 ,匹配,而不是第一个。所以当你运行它时,几乎整条线(除了最后一种植物的颜色)都被这一个.+匹配。
      您可以通过几种不同的方式解决此问题,但最简单的方法是限制您匹配的内容。而不是说.+&#34;匹配任何内容&#34;,而在开始时将其设为[\w\s]+ - 这意味着匹配&#34;字符&#34; (包括字母和数字)或空格字符(因为植物名称中间有一个空格) ($string =~ m/([\w\s]+)+\,+\#+\w{6}/gs)
      这会改变输出,但仍然没有改变完全正确的版本,因为:

    2. m/some regex/g在此处返回其匹配列表作为列表,我们想要的是返回整个匹配,包括植物名称和颜色。但是,当匹配内部存在paranthesis时,m/仅返回与paranthesis匹配的部分(这里是植物名称),而不是整个匹配。因此,删除paranthesis,它变为:
      ($string =~ m/[\w\s]++\,+\#+\w{6}/gs)

这很有效,但是非常笨拙且容易出错,所以这里有一些改进建议:

  • 由于您的输入没有换行符,因此最后的/ s是不必要的 ($string =~ m/[\w\s]++\,+\#+\w{6}/g)
  • ,#不是perl正则表达式中的特殊字符,因此他们在它们之前不需要\
    ($string =~ m/[\w\s]++,+#+\w{6}/g)
  • +是指当你只知道角色会出现时,但不知道它会在那里出现多少次。在此,由于我们只是尝试匹配一个 ,一个 #字符,因此+之后是不必要的。
    ($string =~ m/[\w\s]++,#\w{6}/g)
  • [\ w \ s]之后的++意味着与+完全不同(基本上比平时更加​​贪婪),所以让它成为一个{{1} }
    +
  • 或者,您可以更改最后一个($string =~ m/[\w\s]+,#\w{6}/g)以仅匹配将出现在颜色代码中的十六进制字符:
    \w

这是一个非常可靠,正常的表达式,可以满足您的需求。