регулярное выражение и экранированный символ в схеме

#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")