Расщепление сложной строки с помощью регулярных выражений - PullRequest
1 голос
/ 26 мая 2009

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

string = "a[a=d b&c[e[100&2=34]]] e[cheese=blue and white] x[a=a b]"

в этот массив :

string.split( regexp ) =>

[ "a[a=d b&c[e[100&2=34]]]", "e[cheese=blue and white]", "x[a=a b]" ]

Основное правило состоит в том, что строка должна быть разбита на пробел (\ s) , если пробел не существует внутри скобок ([]) ; * * тысяча двадцать-один

Ответы [ 4 ]

5 голосов
/ 26 мая 2009

Вы не можете; регулярные выражения основаны на конечных автоматах, у которых нет «стека», поэтому вы можете запомнить количество уровней вложенности.

Но, возможно, вы можете использовать хитрость: попробуйте преобразовать строку в действительную строку JSON . Затем вы можете использовать eval(), чтобы разобрать его в объект JavaScript.

4 голосов
/ 26 мая 2009

Если правило очень простое, я бы предложил сделать это вручную. Пройдите через каждого персонажа и следите за уровнем вложенности, увеличивая на 1 для каждого [и уменьшая на 1 для каждого]. Если вы достигнете места с вложенностью == 0, то разделитесь.

Edit: Я подумал, что мог бы также упомянуть, что в некоторых языках есть другие средства сопоставления с образцом, которые изначально поддерживают подобные вещи. Например, в Lua вы можете использовать «% b []» для сопоставления сбалансированных вложенных []. (Конечно, у Lua нет встроенной функции разбиения ....)

0 голосов
/ 26 мая 2009

Другим является циклический подход, при котором вы разбираете вложенные скобки по одному уровню за раз, иначе трудно (TM) обеспечить, чтобы ваше регулярное выражение работало должным образом.

Вот пример в ruby:

str = "a[a=d b&c[e[100&2=34]]] e[cheese=blue and white] x[a=a b]"
left = str.dup
tokn=0
toks=[]
# Deconstruct
loop do
  left.sub!(/\[[^\]\[]*\]/,"\{#{tokn}\}")
  break if $~.nil?
  toks[tokn]=$&
  tokn+=1
end
left=left.split(/\s+/)
# Reconstruct
(toks.size-1).downto(0) do |tokn|
  left.each { |str| str.sub!("\{#{tokn}\}", toks[tokn]) }
end

Выше используется {n}, где n - целое число во время деконструкции, поэтому в некоторых случаях исходный ввод, такой как этот, в строке может нарушить реконструкцию. Это должно проиллюстрировать подход.

Написание кода, который выполняет разбиение путем итерации по символам, проще и безопаснее.

Пример в ruby:

str = "a[a=d b&c[e[100&2=34]]] e[cheese=blue and white] x[a=a b]"
toks=[]
level=st=en=0; 
str.each_byte do |c|
  en+=1; 
  level+=1 if c=='['[0]; 
  level-=1 if c==']'[0]; 
  if level==0 && c==' '[0]
    toks.push(str[st,en-1-st]);
    st=en
  end
end    
toks.push(str[st,en-st]) if st!=en 
p toks
0 голосов
/ 26 мая 2009

не могли бы вы разделить на "(? <=]) \ S (? = [A-z] [)"? то есть пробел, перед которым стоит], за которым следуют буква и [? Это предполагает, что у вас никогда не будет строк внутри скобок, таких как "a [b = d [x = y b] g [w = v b]]" </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...