2015-12-03 3 views
0

У меня есть две строки. Один из них имеет параметры, которые являются уникальными именами в фигурных скобках. Может быть любое количество параметров с любым именем.Сравнение строк без параметров

  1. Я хочу знать, соответствуют ли они, за исключением параметризованных частей. Параметризованные разделы могут быть несколькими словами и любой длиной.
  2. Я хочу сохранить параметризованные части в хэш с ключом, являющимся именем параметра, не включая фигурные скобки.

К примеру, со следующими строками:

Строка 1:

This string is called Fred and Johnson and is very interesting 

Строка 2:

This string is called {name} and is {rating} interesting 

Я хотел бы сохранить:

parameters = {"name" => "Fred and Johnson", "rating" => "very"} 

Любая помощь в том, как я могу это сделать?

+0

Что происходит, когда файлы не совпадают в одной строке? Что произойдет, если в одном файле есть вставленная или удаленная строка? – Amadan

+0

Забудьте, что я упомянул два файла. Я просто сравниваю две строки за один раз, в том же примере, что и выше. Когда строки не совпадают, я просто возвращаю false. Если они совпадают, я беру параметры и возвращаю true. – Scotty

+0

Что происходит, если есть несколько способов совпадения? Например, String 2: '" {foo} и {bar} "', String 1: '" A и B, C и D и E "'. Какими будут «параметры»? – sawa

ответ

6
line1 = "This file is called Fred and Johnson and is very interesting" 
line2 = "This file is called {name} and is {rating} interesting" 

def match_lines(line1, line2) 
    line2_re_code = Regexp.escape(line2).gsub(/\\{(.+?)\\}/, '(?<\1>.+?)') 
    line2_re = Regexp.new("^#{line2_re_code}$") 
    if match = line2_re.match(line1) 
    hash = Hash[match.names.map { |name| [name, match[name]] }] 
    puts hash.inspect 
    else 
    puts "No match" 
    end 
end 

match_lines(line1, line2) 
# => { "name" => "Fred and Johnson", "rating" => "very" } 
match_lines(line1, "foo") 
# => No match 
match_lines("foo", line2) 
# => No match 

EDIT: добавлены якоря. Кроме того, объяснение:

Мы сделаем регулярное выражение из шаблона линии, от первого побега при помощи специальных символов, которые дают это:

'This\ file\ is\ called\ \{name\}\ and\ is\ \{rating\}\ interesting' 

Затем мы переходим заполнители в Oniguruma имени захватов:

'This\ file\ is\ called\ (?<name>.+?)\ and\ is\ (?<rating>.+?)\ interesting' 

, а затем добавить якоря и сделать регулярное выражение из него, чтобы убедиться, что line1 не имеет материал в передней или оборванных на конце:

/^This\ file\ is\ called\ (?<name>.+?)\ and\ is\ (?<rating>.+?)\ interesting$/ 

EDIT2: Regexp#match вернет nil, если матч не удался, или объект MatchData; вы можете использовать MatchData#[] для доступа к отдельным значениям заполнителя. Вы можете использовать MatchData#names, чтобы увидеть, какие заполнители присутствовали.

EDIT3: Ой ... Как сказано в комментариях, names должно было быть match.names.

+2

Очень интересно, но я не уверен, что проблема четко определена.Например, если 'line1 =" Этот файл называется Fred и является Johnson и очень интересен ", то' match_lines (line1, line2) # => Name: Fred, рейтинг: Johnson и очень. –

+0

@CarySwoveland: Конечно, это один из возможных способов сопоставления этого предложения. * shrug * – Amadan

+0

@ Джордан: Я не избегаю пробелов. 'Regexp # escape' есть. И пространство является полностью особым символом в Oniguruma regexp, если вы включите опцию 'x'; 'Regexp # escape' не может знать, будет ли он включен или нет, а если нет, обратное слэш-пространство эквивалентно пространству, поэтому нет никакого вреда. – Amadan

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