【问题标题】:split function extension拆分功能扩展
【发布时间】:2010-01-11 07:30:26
【问题描述】:

我正在从split function 学习示例代码。

示例代码。

#!C:\Perl\bin\perl.exe
use strict;
use warnings;

my $info = "Caine:Michael:Actor:14, Leafy Drive";
my @personal = split(/:/, $info);
# @personal = ("Caine", "Michael", "Actor", "14, Leafy Drive");

如果更改$info = "Caine Michael Actor /* info data */"; 如何使用split(/ /, $info)导出下面的结果。

# @personal = ("Caine", "Michael", "Actor", "info data");

谢谢。

【问题讨论】:

  • 您在哪一部分遇到了困难?到目前为止,您尝试过什么?
  • 嗨,以太,也许我发布了一个愚蠢的问题。我的项目仍然有一些困难。有时我不知道如何分析我的问题,也许我已经以错误的方式发布我的问题。 :-) 我只是尝试了错误的方式,然后我会转身寻找另一种方式。这是我非常愚蠢的学习方法。
  • 是否有充分的理由使用空格作为分隔符?下面的代码示例表明歧义会产生复杂性。一种常见的方法是“转义”分隔符,例如使用反斜杠
  • @Sam and Either,根据 codadict 的回复,对于我的情况来说,这是一个非常复杂的解决方案。下一次,我应该对我的问题本身做更多的分析。然后在这里发布一个确切的要求。 :-) – Nano HE 6 分钟前

标签: perl split


【解决方案1】:

替代方法:

您是否考虑过使用 3 参数版本的 split:

$info = "Caine Michael Actor /* info data */";
@personal= split(' ',$info,4);

导致

@personal=('Caine','Michael','Actor','/* info data */');

那么你必须删除/ * * / .. 才能得到你的结果......

【讨论】:

  • 您好 Lexu,谢谢您的回复。我以前从未考虑过使用 3 参数版本的 split。你教会了我更多关于 split() 的知识。
【解决方案2】:

最好使用正则表达式:

$info = "Caine Michael Actor /* info data */";
$info =~ /(\w+)\s+(\w+)\s+(\w+).*\/\*(.+)\*\//;
@personal = ($1, $2, $3, $4);

主要是因为您的输入字符串存在与 split 不易处理的单词分隔符相关的歧义。

如果您想知道如何阅读正则表达式:

/
    (\w+)   # CAPTURE a sequence of one of more word characters into $1
    \s+     # MATCH one or more white space
    (\w+)   # CAPTURE a sequence of one of more word characters into $2
    \s+     # MATCH one or more white space
    (\w+)   # CAPTURE a sequence of one of more word characters into $3
    .*      # MATCH zero or more of anything
    \/\*    # MATCH the opening of C-like comment /*
    (.+)    # CAPTURE a sequence of one or more of anything into $4
    \*\/    # MATCH the closing of C-like comment */
/x

【讨论】:

  • 通过使用不同的分隔符来避免倾斜牙签综合症并将匹配项分配给@personal。不要忘记检查@personal 是否已填充。 if ( @personal =~ m!...! )。您还应该锚定模式。
  • 你真的不想在那里匹配 \w+ 。你不关心字符是什么,只要它们不是空格(也就是说,你不关心它们是否是 Perl 标识符字符),所以你应该匹配 \S+
  • 最好是if (@personal = $info =~ /.../) { ... }永远不要无条件使用$1和朋友!
【解决方案3】:

由于还没有解决一般情况的答案,所以这里是:

split 不是你最好的选择,因为分隔符既可以是匹配字符也可以是不匹配字符,最清楚的是反转问题并描述你做什么匹配,在这种情况下是可以是一串非空格字符,也可以是 c 样式注释的内容。

use strict;
use warnings;

my $info = "Caine Michael Actor /* info data */";
my @personal = grep {defined} $info =~ m! /\* \s* (.+?) \s* \*/ | (\S+) !xg;

say join ', ' => @personal;

这将以您需要的任何顺序返回 cmets 的单词/内容列表。语法高亮没有正确高亮上面的正则表达式,正则表达式是! 之间的所有内容

【讨论】:

    【解决方案4】:

    煮了一些东西:)。仅适用于您的示例。无法概括

    use strict;
    use warnings;
    
    my $info = "Caine Michael Actor /* info data */";
    if($info=~m{/\*\s*(.*?)\s*\*/})
    {
        my $temp = $1;
        $temp=~s{\s+}{##}g;
        $info=~s{/\*\s*(.*?)\s*\*/}{$temp};
    }
    my @personal = split(/ /, $info);
    foreach(@personal)
    {
        s{##}{ }g;
        print "$_\n";
    }
    

    输出:

    C:>perl a.pl 凯恩 迈克尔 演员 信息数据

    【讨论】:

    • @codadict,非常感谢您的详细回复。我发现这是我的情况的解决方案。这很神奇。
    猜你喜欢
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2013-02-08
    • 2022-01-09
    • 2011-10-10
    • 2020-02-14
    • 2018-02-12
    • 1970-01-01
    相关资源
    最近更新 更多