2012-04-24 4 views
6

Рубин (1.9.3) документации, кажется, подразумевает, что сканирование эквивалентно = ~ кроме того, чторубин регулярное выражение сканирования по сравнению с = ~

  1. сканирования возвращает несколько совпадений, а = ~ возвращает только первое вхождение, и
  2. scan возвращает данные сопоставления, а = ~ возвращает индекс.

Однако в следующем примере два метода возвращают разные результаты для одной и той же строки и выражения. Почему это?

1.9.3p0 :002 > str = "Perl and Python - the two languages" 
=> "Perl and Python - the two languages" 
1.9.3p0 :008 > exp = /P(erl|ython)/ 
=> /P(erl|ython)/ 
1.9.3p0 :009 > str =~ exp 
=> 0 
1.9.3p0 :010 > str.scan exp 
=> [["erl"], ["ython"]] 

Если индекс первого матча 0, не следует сканировать возвращение «Perl» и «Python» вместо «Эрл» и «питон»?

Благодаря

ответ

12

Когда дано регулярное выражение без захвата групп, scan возвращает массив строк, где каждая строка представляет матч регулярного выражения. Если вы используете scan(/P(?:erl|ython)/) (что совпадает с вашим регулярным выражением, за исключением групп захвата), вы получите ["Perl", "Python"], что и ожидалось.

Однако, если задано регулярное выражение с группами захвата, scan вернет массив массивов, где каждый подматрица содержит записи определенного совпадения. Итак, если у вас есть, например, регулярное выражение (\w*):(\w*), вы получите массив массивов, в котором каждый суб-массив содержит две строки: часть перед двоеточием и часть после двоеточия. И в вашем примере каждый под-массив содержит одну строку: часть, сопоставляемая (erl|ython).

+0

Спасибо, поэтому сканирование строго не эквивалентно = ~, когда есть группы, участвующие? – Anand

+2

@Anand Поскольку сканирование возвращает что-то совершенно иное, чем = ~, я не думаю, что когда-либо точно сказать, что они эквивалентны. Первым результатом, возвращаемым сканированием, будет подстрока, начинающаяся с индекса 'str = ~ exp' тогда и только тогда, когда' exp' не содержит группы захвата. В дополнение к этому вы также можете сказать, что первый результат будет эквивалентен 'Regexp.last_match.string' после выполнения' str = ~ exp', если он не содержит групп захвата и 'Regexp.last_match.captures', если он содержит группы захвата. – sepp2k

+0

Рад видеть этот пост, от которого вы действительно можете учиться. – texasbruce

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