Подтвердить что ты не робот

Как я могу извлечь подстроки из строки в Perl?

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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:

\(([^)]+)\)

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

\s*(\*)?

Ответ 2

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

/([-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

(\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 *

Ответ 4

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

while(<STDIN>) {
    next unless /:\s*(\S+)\s+\(([^\)]+)\)\s*(\*?)/;
    print "|$1|$2|$3|\n";
}

Ответ 5

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

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

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

#!/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) ... }     

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

Ответ 6

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

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;

Ответ 7

Строка 1:

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

Строка 2:

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

Строка 3:

$input =~ /\*?$/;
$s3 = $&;