2013-05-06 2 views
0

У меня есть переменная String, содержащая что-то вроде ABCD.asd.qwe.com:/dir1. Я хочу извлечь часть ABCD, то есть часть от начала до первого появления .. Проблема в том, что перед . могут быть почти любые символы (только буквенно-цифровые) любой длины. Поэтому я создал это регулярное выражение.Perl Regular Выражение подстроки выражения Expression?

if($arg =~ /(.*?\.?)/) 
{ 
    my $temp_name = $1; 
} 

Однако это дает мне пустую строку. Логика такова:

.*? - any character non-greedily 
\.? - till first or none appearance of . 

Что может быть неправильным?

+0

Вы пытаетесь извлечь 'ABCD' или' ABCD.'? Будет ли '.' всегда присутствовать на входе? – ikegami

+0

Я хочу извлечь только ABCD и не включая точку. –

+0

Как насчет моего второго вопроса. Всегда ли будет входной сигнал '. '? – ikegami

ответ

3

Вы можете вместо этого использовать отрицательный класс персонажа как этот

^[^.]+ 

[^.] будет соответствовать любому символу, кроме .

[^.]+ будет соответствовать 1 по многим признакам (кроме .)

^ изображает начало строки

ИЛИ

^.+?(?=\.|$) 

(?=) является опережением, который проверяет наличие определенного шаблона после текущего position..So для текста abcdad с регулярным выражением a(?=b) только a будет соответствовать

$ изображает конец строки (если используется с многострочной опцией) или конец строки (если используется с опцией одиночной линии)

+0

Эй, @ Анируд, оба решения работают! Спасибо, человек! Но не могли бы вы объяснить логику этого? –

+0

@Cool_Coder Логика очень проста. Первый символ '^' означает '' строка должна начинаться здесь' '. Следующий '[^.] +' Означает «любой символ, который не является периодом, повторяется 1 или более раз». Следовательно, он выбирает до первого периода. – h2ooooooo

+0

@Cool_Coder проверить редактирование ... @ Крутые спасибо – Anirudha

3

\.? не означает «до первого или любого вида .». Это означает «. здесь или нет».


Если первый символ строки является .:

  • .*? матчи 0 гольцов в положении 0.
  • \.? Матчей 1 символ в позиции 0.

$1 содержит ..


Если первый символ строки не .:

  • .*? матчи 0 гольцов в положении 0.
  • \.? спичек 0 гольцов в положении 0.

$1 пусто.


Чтобы соответствовать ABCD, следующий будет делать:

/^(.*?)\./ 

Однако, я ненавижу нежадным модификатор. Он хрупкий, в том смысле, что он перестает делать то, что вам нужно, если вы используете два в одном шаблоне. Я хотел бы использовать следующие вместо ("соответствует не-периодов"):

/^([^.]*)\./ 

или даже просто

/^([^.]*)/ 
+0

(«^» не обязательно, но это хорошая привычка, так как это может предотвратить сумасшедшее количество отказов при сбое.) – ikegami

+0

Спасибо, что объяснили неправильность моего первоначального подхода. –

2
use strict; 

my $string = "ABCD.asd.qwe.com:/dir1"; 

$string =~ /([^.]+)/; 
my $capture = $1; 
print"$capture\n"; 

ИЛИ вы можете также использовать Split функция как,

my $sub_string = (split /\./, $string)[0]; 
print"$sub_string\n"; 

Примечание в целом: Для объяснений от Regex (понимание Комплексы x Regex), посмотрите на модуль YAPE::Regex::Explain.

+0

спасибо за сплит-подход :) –

+1

'my ($ capture) = $ string = ~ /^([^.]+)/;' будет более надежным. (Бонус: не использует глобальные вары.) – ikegami

+0

вправо, согласовано. Спасибо –

0

Это должно работать:

if($arg =~ /(.*?)\..+/) 
{ 
    my $temp_name = $1; 
} 

Это соответствовало бы что-нибудь перед первым .. Вы можете изменить .+ на. * Если ваш вход может закончиться после первого .. Вы можете изменить первый .*? к .+?, если вы уверены, что всегда есть по крайней мере один символ перед первой ..

+0

Добавленный '. +' Бесполезен. Во-первых, это то же самое, что просто '.'. Во-вторых, все, что он делает, это убедиться, что за символом '.' следует не-новая строка, и ОП не проявил никакого интереса к проверке этого. Так почему вы его добавили? – ikegami

Смежные вопросы