Split line with perl

前端 未结 5 649
深忆病人
深忆病人 2021-01-23 03:57
   title: Football team: Real Madrid stadium: Santiago Bernabeu players: Zinédine Zidane, Ronaldo, Luís Figo, Roberto Carlos, Raúl personnel: José Mourinho (head coach)          


        
相关标签:
5条回答
  • 2021-01-23 04:28

    Contrary to what many are saying in their answers, you do not need lookahead (other than the Regex's own), you would only need to capture part of the delimiter, like so:

    my @hash_fields = grep { length; } split /\s*(\w+):\s*/;
    

    My full solution below:

    my %handlers
        = ( players   => sub { return [ grep { length; } split /\s*,\s*/, shift ]; }
          , personnel => sub { 
                my $value = shift;
                my %personnel;
                # Using recursive regex for nested parens
                while ( $value =~ m/([^(]*)([(](?:[^()]+|(?2))*[)])/g ) {
                    my ( $name, $role ) = ( $1, $2 );
                    $role =~ s/^\s*[(]\s*//;
                    $role =~ s/\s*[)]\s*$//;
                    $name =~ s/^\s+//;
                    $name =~ s/\s+$//;
                    $personnel{ $role } = $name;
                }
                return \%personnel;
            }
          );
    my %hash = grep { length; } split /(?:^|\s+)(\w+):\s+/, <DATA>;
    foreach my $field ( keys %handlers ) { 
        $hash{ $field } = $handlers{ $field }->( $hash{ $field } );
    }
    

    Dump looks like this:

    %hash: {
         personnel => {
                        'assistant coach (es)' => 'Aitor Karanka',
                        'head coach' => 'José Mourinho'
                      },
         players => [
                      'Zinédine Zidane',
                      'Ronaldo',
                      'Luís Figo',
                      'Roberto Carlos',
                      'Raúl'
                    ],
         stadium => 'Santiago Bernabeu',
         team => 'Real Madrid',
         title => 'Football'
       }
    
    0 讨论(0)
  • 2021-01-23 04:32

    This should do it. line.txt contains "title: Football team: Real Madrid stadium: Santiago Bernabeu players: Zinédine Zidane, Ronaldo, Luís Figo, Roberto Carlos, Raúl personnel: José Mourinho (head coach) Aitor Karanka (assistant coach (es))"

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my $fn="./line.txt";
    
    open(IN,$fn);
    my @lines=<IN>;
    
    my %hash;
    my $hashKey;
    
    foreach my $line (@lines){
            $line=~s/\n//g;
            my @split1=split(" +",$line);
            foreach my $split (@split1){
                    if($split=~m/:$/){
                            $hashKey=$split;
                    }else{
                            if(defined($hash{$hashKey})){
                                    $hash{$hashKey}=$hash{$hashKey}.$split." ";
                            }else{
                                    $hash{$hashKey}=$split." ";
                            }
                    }
            }
    }
    
    close(IN);
    
    
    foreach my $key (keys %hash){
            print $key.":".$hash{$key}."\n";
    }
    
    0 讨论(0)
  • 2021-01-23 04:34

    Use a lookahead assertion:

    say for split /(?=\w+:)/, $real_madrid_string;
    

    Output

    title: Football
    team: Real Madrid
    stadium: Santiago Bernabeu
    players: Zinédine Zidane Ronaldo Luís Figo Roberto Carlos Raúl
    personnel: José Mourinho (head coach) Aitor Karanka (assistant coach (es))
    
    0 讨论(0)
  • 2021-01-23 04:43

    The best way is to use the split command using a zero-width lookahead:

    $string = "title: Football team: Real Madrid stadium: Santiago Bernabeu players: Zinédine Zidane, Ronaldo, Luís Figo, Roberto Carlos, Raúl personnel: José Mourinho (head coach) Aitor Karanka (assistant coach (es))";
    
    @split_string = split /(?=\b\w+:)/, $string;
    
    0 讨论(0)
  • 2021-01-23 04:49
    $string = "title: Football team: Real Madrid stadium: Santiago Bernabeu players: Zinédine Zidane, Ronaldo, Luís Figo, Roberto Carlos, Raúl personnel: José Mourinho (head coach) Aitor Karanka (assistant coach (es))";
    @words = split(' ', $string);
    
    @lines = undef;
    @line = shift(@words);
    foreach $word (@words)
    {
        if ($word =~ /:/)
        {
            push(@lines, join(' ', @line));
            @line = undef;
        }
        else
        {
            push(@line, $word);
        }
    }
    
    print join("\n", @lines);
    
    0 讨论(0)
提交回复
热议问题