Как я могу извлечь подстроки из строки в Perl? - PullRequest
12 голосов
/ 18 сентября 2009

Рассмотрим следующие строки:

1) Идентификатор схемы: abc-456-hu5t10 ( Высокий приоритет ) *****

2) Идентификатор схемы: frt-78f-hj542w ( Сбалансированный )

3) Идентификатор схемы: 23f-f974-nm54w ( супер формула запуска ) *****

и т. Д. В указанном выше формате - части, выделенные жирным шрифтом, являются изменениями в строках.

==> Представьте, что у меня много строк формата, показанных выше. Я хочу выбрать 3 подстроки (как показано ниже жирным шрифтом) из каждой из указанных выше строк.

  • 1-ая подстрока, содержащая буквенно-цифровое значение (например, выше, это «abc-456-hu5t10»)
  • 2-ая подстрока, содержащая слово (например, над ним «Высокий приоритет»)
  • 3-я подстрока, содержащая * (IF * присутствует в конце строки ELSE оставить ее)

Как мне выбрать эти 3 подстроки из каждой строки, показанной выше? Я знаю, что это можно сделать с помощью регулярных выражений в Perl ... Можете ли вы помочь с этим?

Ответы [ 7 ]

30 голосов
/ 18 сентября 2009

Вы можете сделать что-то вроде этого:

my $data = <<END;
1) Scheme ID: abc-456-hu5t10 (High priority) *
2) Scheme ID: frt-78f-hj542w (Balanced)
3) Scheme ID: 23f-f974-nm54w (super formula run) *
END

foreach (split(/\n/,$data)) {
  $_ =~ /Scheme ID: ([a-z0-9-]+)\s+\(([^)]+)\)\s*(\*)?/ || next;
  my ($id,$word,$star) = ($1,$2,$3);
  print "$id $word $star\n";
}

Ключевым моментом является регулярное выражение:

Scheme ID: ([a-z0-9-]+)\s+\(([^)]+)\)\s*(\*)?

Что разбивается следующим образом.

Фиксированная строка «Идентификатор схемы:»:

Scheme ID: 

Вслед за одним или несколькими символами a-z, 0-9 или -. Мы используем скобки, чтобы зафиксировать это как $ 1:

([a-z0-9-]+)

После одного или нескольких пробельных символов:

\s+

Далее следует открывающая скобка (от которой мы убегаем), за которым следует любое количество символов, которые не являются закрывающей скобкой, а затем закрывающая скобка (экранированная) Мы используем неэкранированные скобки, чтобы зафиксировать слова как $ 2:

\(([^)]+)\)

За ними следуют некоторые пробелы, возможно, *, захваченные как $ 3:

\s*(\*)?
3 голосов
/ 18 сентября 2009

Вы можете использовать регулярное выражение, такое как:

/([-a-z0-9]+)\s*\((.*?)\)\s*(\*)?/

Так, например:

$s = "abc-456-hu5t10 (High priority) *";
$s =~ /([-a-z0-9]+)\s*\((.*?)\)\s*(\*)?/;
print "$1\n$2\n$3\n";

печать

abc-456-hu5t10
High priority
*
3 голосов
/ 18 сентября 2009
(\S*)\s*\((.*?)\)\s*(\*?)


(\S*)    picks up anything which is NOT whitespace
\s*      0 or more whitespace characters
\(       a literal open parenthesis
(.*?)    anything, non-greedy so stops on first occurrence of...
\)       a literal close parenthesis
\s*      0 or more whitespace characters
(\*?)    0 or 1 occurances of literal *
2 голосов
/ 18 сентября 2009

Ну, один лайнер здесь:

perl -lne 'm|Scheme ID:\s+(.*?)\s+\((.*?)\)\s?(\*)?|g&&print "$1:$2:$3"' file.txt

Расширена до простого сценария, чтобы объяснить вещи немного лучше:

#!/usr/bin/perl -ln              

#-w : warnings                   
#-l : print newline after every print                               
#-n : apply script body to stdin or files listed at commandline, dont print $_           

use strict; #always do this.     

my $regex = qr{  # precompile regex                                 
  Scheme\ ID:      # to match beginning of line.                      
  \s+              # 1 or more whitespace                             
  (.*?)            # Non greedy match of all characters up to         
  \s+              # 1 or more whitespace                             
  \(               # parenthesis literal                              
    (.*?)            # non-greedy match to the next                     
  \)               # closing literal parenthesis                      
  \s*              # 0 or more whitespace (trailing * is optional)    
  (\*)?            # 0 or 1 literal *s                                
}x;  #x switch allows whitespace in regex to allow documentation.   

#values trapped in $1 $2 $3, so do whatever you need to:            
#Perl lets you use any characters as delimiters, i like pipes because                    
#they reduce the amount of escaping when using file paths           
m|$regex| && print "$1 : $2 : $3";

#alternatively if(m|$regex|) {doOne($1); doTwo($2) ... }     

Хотя, если бы это было что-то иное, чем форматирование, я бы реализовал основной цикл для обработки файлов и уточнения тела сценария, а не полагался на переключатели командной строки для цикла.

1 голос
/ 19 сентября 2009

Это просто требует небольшого изменения моего последнего ответа :

my ($guid, $scheme, $star) = $line =~ m{
    The [ ] Scheme [ ] GUID: [ ]
    ([a-zA-Z0-9-]+)          #capture the guid
    [ ]
    \(  (.+)  \)             #capture the scheme 
    (?:
        [ ]
        ([*])                #capture the star 
    )?                       #if it exists
}x;
1 голос
/ 18 сентября 2009

Долгое время нет Perl

while(<STDIN>) {
    next unless /:\s*(\S+)\s+\(([^\)]+)\)\s*(\*?)/;
    print "|$1|$2|$3|\n";
}
0 голосов
/ 18 сентября 2009

Строка 1:

$input =~ /'^\S+'/;
$s1 = $&;

Строка 2:

$input =~ /\(.*\)/;
$s2 = $&;

Строка 3:

$input =~ /\*?$/;
$s3 = $&;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...