регулярное выражение и экранированный символ в схеме - PullRequest
3 голосов
/ 21 мая 2011

в схеме,

есть "hello hellu-#\"hella.helloo,hallo#\return#\"" строка

Я хочу перечислить их как ("hello" "hellu" "hella" "helloo" "hallo")

разделяйте пробелом, дефисом, двойной кавычкой, точкой, запятой, возвращайте

Я пытался

(regexp-split #rx"( +)|(#\-)|(#\")|(#\.)|(,)|(#\return)" string)

, но #\- , #\. допускал ошибку

любой намек или решение?

спасибо

1 Ответ

3 голосов
/ 21 мая 2011

Похоже, вы путаете синтаксис для символов (#\foo) с синтаксисом для строк, и вы делаете это как в строке, так и в регулярном выражении.Поэтому я предполагаю, что строка, которую вы хотите разделить, на самом деле:

"hello hellu-\"hella.helloo,hallo\n\""

, где \" обозначает символ двойной кавычки, а \n - символ новой строки.Если это так, то (опять же, это угадывает ваше намерение) регулярное выражение должно быть:

(regexp-split #rx"( +)|(\-)|(\")|(\.)|(,)|(\n)" string)

Но это тоже не работает, поскольку \- и \. являются недопустимыми escape-символами (Racket использует C-подобные переходы), поэтому измените его на:

(regexp-split #rx"( +)|(-)|(\")|(.)|(,)|(\n)" string)

Это тоже не работает, так как . имеет обычное значение "любой символ" в регулярном выражении - так что вы хотитеизбежать этого с обратной косой чертой.Как и во многих других строковых синтаксисах, вы получаете обратную косую черту, экранируя ее обратной косой чертой, поэтому теперь у нас есть версия, которая, наконец, близка к рабочей:

> (define string "hello hellu-\"hella.helloo,hallo\n\"")
> (regexp-split #rx"( +)|(-)|(\")|(\\.)|(,)|(\n)" string)
'("hello" "hellu" "" "hella" "helloo" "hallo" "" "")

Во-первых, регулярное выражение может быть значительно улучшено: паренсы не нужны для разделения:

(regexp-split #rx" +|-|\"|\\.|,|\n" string)

Затем, вместо использования набора одиночных символов с | s, вы можете просто использовать «диапазон символов»:

(regexp-split #rx" +|[-\".,\n]" string)

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

(regexp-split #rx" +|[-\".,\n]+" string)

, и в этом случае вы можете такжебросить пробел в диапазон тоже (осторожно поместив его после * -, как я объяснил выше).Теперь мы получаем:

> (define string "hello hellu-\"hella.helloo,hallo\n\"")
> (regexp-split #rx"[- \".,\n]+" string)
'("hello" "hellu" "hella" "helloo" "hallo" "")

И, наконец, вы, вероятно, захотите избавиться от этой последней пустой строки.Технически, это должно быть там, поскольку перед концом строки есть последовательность совпадающих символов.Простой способ обойти это в Racket - использовать дополнительный regexp-match*, который возвращает список совпадений , вместо разделения на список совпадений:

> (define string "hello hellu-\"hella.helloo,hallo\n\"")
> (regexp-match* #rx"[- \".,\n]+" string)
'(" " "-\"" "." "," "\n\"")

Это явно не работает,так как он дает вам разделители, а не то, что между ними.Но так как это регулярное выражение является диапазоном символов, его легко разрешить - просто отмените диапазон символов, и вы получите то, что хотите:

> (define string "hello hellu-\"hella.helloo,hallo\n\"")
> (regexp-match* #rx"[^- \".,\n]+" string)
'("hello" "hellu" "hella" "helloo" "hallo")
...