#regex #scheme #escaping #split #racket
#регулярное выражение #схема #экранирование #разделение #racket
Вопрос:
в схеме,
есть "hello hellu-#"hella.helloo,hallo#return#""
строка
Я хочу перечислить их как («привет», «хеллу», «хелла», «хеллу», «алло»)
разделять пробелом, дефисом, двойными кавычками, точкой, запятой, возвращать
Я пытался
(regexp-split #rx"( )|(#-)|(#")|(#.)|(,)|(#return)" string)
но #- , #.
выдает ошибку
есть какой-нибудь намек или решение?
Спасибо
Ответ №1:
Похоже, вы путаете синтаксис символов ( #foo
) с синтаксисом строк, и вы делаете это как в строке, так и в регулярном выражении. Итак, я предполагаю, что строка, которую вы хотите разделить, на самом деле:
"hello hellu-"hella.helloo,hallon""
где "
обозначает символ двойной кавычки и n
символ новой строки. Если это так, то (опять же, это угадывание вашего намерения) регулярное выражение должно быть:
(regexp-split #rx"( )|(-)|(")|(.)|(,)|(n)" string)
Но это тоже не работает, поскольку -
и .
являются недопустимыми экранированиями (Racket использует C-подобные экранирования), поэтому измените это на:
(regexp-split #rx"( )|(-)|(")|(.)|(,)|(n)" string)
Это тоже не работает, поскольку .
имеет обычное значение «любой символ» в регулярном выражении — поэтому вы хотите экранировать его с помощью обратной косой черты. Как и во многих других строковых синтаксисах, вы получаете обратную косую черту, экранируя ее обратной косой чертой, так что теперь у нас есть версия, которая, наконец, близка к рабочей:
> (define string "hello hellu-"hella.helloo,hallon"")
> (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,hallon"")
> (regexp-split #rx"[- ".,n] " string)
'("hello" "hellu" "hella" "helloo" "hallo" "")
И, наконец, вы, вероятно, захотите избавиться от этой последней пустой строки. Технически, это должно быть там, поскольку перед концом строки есть последовательность совпадающих символов. Простой способ обойти это — использовать дополнительный, regexp-match*
который возвращает список совпадений, а не разбивает список совпадений:
> (define string "hello hellu-"hella.helloo,hallon"")
> (regexp-match* #rx"[- ".,n] " string)
'(" " "-"" "." "," "n"")
Это, очевидно, нарушено, поскольку оно предоставляет вам разделители, а не то, что между ними. Но поскольку это регулярное выражение представляет собой диапазон символов, его легко разрешить — просто отрицайте диапазон символов, и вы получите то, что хотите:
> (define string "hello hellu-"hella.helloo,hallon"")
> (regexp-match* #rx"[^- ".,n] " string)
'("hello" "hellu" "hella" "helloo" "hallo")