【问题标题】:How to print beginning of string?如何打印字符串的开头?
【发布时间】:2012-03-16 10:00:34
【问题描述】:

如果我有

$t = '20110512102331';

并且只想要来自$t 的前 4 个字符。

我该怎么做?

【问题讨论】:

  • 你问了 很多 Perl 问题,通常是非常基本的问题。您现在还没有学会自己搜索文档吗?为什么不呢?
  • 根据您的历史,我认为我的书Learning Perl 会有所帮助。 :)

标签: perl


【解决方案1】:

通过像这样使用substr 函数 -

my $t = "20110512102331";
my $four = substr($t, 0, 4)

【讨论】:

    【解决方案2】:

    对于您的特定问题,从字符串中提取似乎是年份,substr 意外工作,但这里确实是错误的答案。它的“性格”观念不是我们的“性格”观念。注意résumé 的不同归一化形式如何产生不同的结果。您可能需要前四个字素,可以与 \X 匹配(尽管在 ASCII 中字素和字符给出相同的结果)

    use v5.10.1;
    use utf8;
    use strict;
    use warnings;
    
    use Unicode::Normalize qw(NFD NFC);
    
    my $string = '20110512102331';
    say "$string → ", substr $string, 0, 4;
    
    my $ustring = NFD( 'résumé' );
    say "NFD $ustring → ", substr $ustring, 0, 4;
    
    $ustring = NFC( 'résumé' );
    say "NFC $ustring → ", substr $ustring, 0, 4;
    
    $ustring = NFD( 'résumé' );
    say "\\X with NFD $ustring → ", $ustring =~ m/(\X{4})/;
    
    $ustring = NFC( 'résumé' );
    say "\\X with NFC $ustring → ", $ustring =~ m/(\X{4})/;
    

    注意 NFD 结果不同:

    $ perl -C substr.pl
    20110512102331 → 2011
    NFD résumé → rés
    NFC résumé → résu
    \X with NFD résumé → résu
    \X with NFC résumé → résu
    

    不过,substr 确实有一些 Unicode 功夫,如果你给它一个来自 Unicode::GCString 的字符串:

    use v5.10.1;
    use utf8;
    use strict;
    use warnings;
    
    use Unicode::GCString;
    use Unicode::Normalize qw(NFD);
    
    my $gcstring = Unicode::GCString->new( NFD('résumé') );
    say "$gcstring → ", $gcstring->substr( 0, 4 );
    

    这会得到正确的结果:

    $ perl -C gcsubstr.pl
    résumé → résu
    

    但是,所有这些都解决了字符串不仅仅是字符集合的问题。这些字符具有特殊含义,因此您可以使用该特殊含义来做正确的事情,而无需考虑字符串操作。如果您可以描述格式,DateTime::Format::Strptime 是解析任意日期格式的好方法:

    use v5.10.1;
    use utf8;
    use strict;
    use warnings;
    
    use DateTime::Format::Strptime;
    
    my $Strp = DateTime::Format::Strptime->new(
        pattern => '%Y%m%d%H%M%S',
        );
    my $Strf = DateTime::Format::Strptime->new(
        pattern => '%Y',
        );
    
    my $dt = $Strp->parse_datetime('20110512102331');
    
    my $year = $Strf->format_datetime($dt);
    
    say "year is $year";
    

    您可能还想查看How can I parse dates and convert time zones in Perl?

    无论您决定采用何种方式,您都可以将实现细节隐藏在子例程中,这样您就可以在不中断程序其余部分的情况下对其进行更改。

    【讨论】:

      【解决方案3】:

      最简单:使用substr函数:

      my $firstfour = substr($t,0,4); 
      

      另一种方法是使用正则表达式:

      my $firstfour = ($t =~ /(.{0,4}).*/s ? $1 : $t);
      

      或者,更短的,通过在列表上下文中调用正则表达式:

      my ($firstfour) = $t =~ /(.{0,4})/s;
      

      【讨论】:

      • m/(.{4})/ms 更适合“字符串的前四个字符”。当然存在长度小于 4 的字符串的极端情况。标准假设是返回与字符串一样多的字符。所以我们可以在这种情况下做到这一点:m/(.{1,4})/ms.
      • @Axeman:这仍然不能处理空字符串的情况,这将使$firstfour 未定义。 /m 限定符在这里也无关紧要。 /(.{0,4})/s 是正确的。
      • 感谢 Axeman,好点! @Borodin:这取决于字符串为空时会发生什么,但是您的“只返回一个空字符串”是有道理的。我会更新的!
      【解决方案4】:
      $t='20110512102331'; 
      print substr($t, 0, 4);
      

      更多信息请参见perldoc -f substr

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-26
        • 1970-01-01
        • 2015-12-31
        • 1970-01-01
        • 2015-01-26
        • 1970-01-01
        相关资源
        最近更新 更多