Lisp: замена подстрок в строке
Идея, надеюсь, понятна.
---
...Я работаю антинаучным аферистом...
берёшь ту же самую библиотеку RE, и примерно так же пишешь
> (format nil "~A" (cl-ppcre:regex-replace "'" "foo' bar" "\\\\'"
"foo\\' bar"
но как сделать "foo\' bar"?
Задача в чем: у меня есть БД (postgresql) и я хочу через clsql:insert-records добавить в таблицу строку типа text, в которой встречаются '
(use-modules (srfi srfi-13
(define (qt str)
(string-concatenate
(map (lambda (ch) (case ch #\') "\\'")
(else (list->string (list ch
(string->list str
(define (qt str)
(string-concatenate
(map (lambda (ch)
(list->string (if (member ch '(#\' (list #\\ ch) (list ch
(string->list str
(begin (display (qt "te'st" (newline
(define (qts str lst qch)
(string-concatenate
(map (lambda (ch)
(list->string (if (member ch lst) (list qch ch) (list ch
(string->list str
(begin (display (qts "te'#st" (string->list "'#") #\\ (newline
Я не думаю, что воспроизвести это в CL настолько сложно.
> как сделать "foo\' bar"?
Ты уверен, что используешь правильный "print"?
$ guile -l ~/scm/quote-str.scm
te\'st
te\'\#st
guile> (begin (display (qt "te'st" (newline
te\'st
guile> (qt "te'st")
"te\\'st"
---
...Я работаю антинаучным аферистом...
Да, спасибо, ppcre я пробую:
code:> (format nil "~A" (cl-ppcre:regex-replace "'" "foo' bar" "\\\\'"
"foo\\' bar"
но как сделать "foo\' bar"?
Задача в чем: у меня есть БД (postgresql) и я хочу через clsql:insert-records добавить в таблицу строку типа text, в которой встречаются '
CL-USER> (format nil "~A" (cl-ppcre:regex-replace "'" "foo' bar" "\\\\'"
"foo\\' bar"
CL-USER> (length *)
9
Из чего следует, что это печатается 2 бэкслэша, а на самом деле он там один.
CL-USER> (loop for x across ** do (print x
#\f
#\o
#\o
#\\
#\'
#\
#\b
#\a
#\r
NIL
CL-USER>
Кстати, в твоем случае наверное надо использовать функцию regex-replace-all. Еще, если один regex используется много раз, можно сохранить значение (create-scanner regex) и потом использовать это значение вместо этого regex-a.
http://www.tek-tips.com/viewthread.cfm?qid=1184743&page=...
я даже что-то понял про разный print.
странно что в языке нет стандартного средства, оптимизированного как надо.
( defun string-replace ( str1 sub1 sub2 )
( setq str1 ( string str1 ) )
( setq str2 "" )
( setq sub1 ( string sub1 ) )
( setq sub2 ( string sub2 ) )
( setq index1 0 )
( loop
( if
( string-equal str1 sub1 :start1 index1 :end1 ( + index1 ( length sub1 ) ) :start2 0 )
; then
(
( setq str2 ( concatenate 'string str2 sub2 ) )
( setq index1 ( + index1 ( length sub1 ) ) )
)
; else
(
( setq str2 ( concatenate 'string str2 ( char str1 index1 ) ) )
( incf index1 )
)
)
( when ( > index1 ( length str1 ) ) ( return str2 ) )
)
)
я даже что-то понял про разный print.
странно что в языке нет стандартного средства, оптимизированного как надо.
Из этого следует, что "Common" LISP настолько нечитаем,
что некоторые простейшие вещи оказываются вновинку
даже его апологетам:
[[library procedure]] (write obj)
[[library procedure]] (write obj port)
Writes a written representation of obj to the given port. Strings that appear
in the written representation are enclosed in doublequotes, and within those
strings backslash and doublequote characters are escaped by backslashes.
Character objects are written using the #\ notation. Write returns an
unspecified value. The port argument may be omitted, in which case it defaults
to the value returned by current-output-port.
[[library procedure]] (display obj)
[[library procedure]] (display obj port)
Writes a representation of obj to the given port. Strings that appear in the
written representation are not enclosed in doublequotes, and no characters are
escaped within those strings. Character objects appear in the representation
as if written by write-char instead of by write. Display returns an
unspecified value. The port argument may be omitted, in which case it defaults
to the value returned by current-output-port.
Rationale:
Write is intended for producing machine-readable output and display is for
producing human-readable output. Implementations that allow "slashification"
within symbols will probably want write but not display to slashify funny
characters in symbols.
---
...Я работаю дзен-схематиком...
Неужели нет способа проще?
Там же очевидна декомпозиция на поиск подстроки,
отрезание хвоста и склеивание строк скопом.
---
...Я работаю антинаучным аферистом...
склеивание строк скопом
не нашел такой функции.
на питоне она зовется "join".
"\\'".join("foo'bar".split("'"
> не нашел такой функции.
Чёрт!
"fold" у тебя хотя бы есть?
(defun string-concatenate (lst) (fold 'string-concatenate-bin "" lst?
(defun string-concatenate-bin (s1 s2) (concatenate 'string str2 sub2 ; нагло выдернуто из твоего сообщения
"reduce"?
> на питоне она зовется "join".
На схеме, как уже видно, она зовётся "string-concatenate".
Вроде бы, эта задача должна как-то свестись к "unfold" (SRFI-1
но как это сделать, пока неясно. То есть, я не могу сейчас
вплотную заняться решением. Можешь пока что думать сам.
Основная идея: (string-concatenate (map (lambda ... (assoc ... substitutions) ...) (unfold null-string? ? ? string.
---
...Я работаю...
Из этого следует, что "Common" LISP настолько нечитаем,Ты какую-то хуйню написал. Человеку нужна программа на Common Lisp, а всякие схемы и форты в данном случае нахуй не нужны. Вместо того чтобы помочь челу ты постишь какие-то рандомные куски кода и цитаты из манов. Just drop it.
что некоторые простейшие вещи оказываются вновинку
даже его апологетам:
_, строки склеиваются функцией concatenate:
(concatenate 'string "all" " " "together" " " "now") => "all together now"
_, строки склеиваются функцией concatenate:Да это-то я нашел давно.
(concatenate 'string "all" " " "together" " " "now") => "all together now"
![](/images/graemlins/smile.gif)
Но вот есть у меня список и склеить список через заданный delimiter — мне непонятно как это сделать _просто_.
То, что "Common LISP" настолько неподъёмен, что даже ты,
будучи апологетом этого диалекта, не в курсе того, что именно
печатается в REPL (Иначе с чего бы тебе открывать это
определяя длину строки? показывает твоё знание языка.
Кстати, ты не показал, как напечатать строку в читаемом виде,
видимо, не смог найти этого в своём полутонном стандарте.
Я исхожу из того, что схема --- это "One True LISP", что есть правда,
и от этого никуда не деться. Пока что мой опыт не подводил меня
в лисповой области, даже в такой её части, как емакс.
В частности, выдержка из R5RS показывает именно то, что ты
не смог найти в своём фолианте: написал "(length *)" вместо того,
чтобы найти, как у тебя называется "display".
И не надо приплетать сюда форт, до тебя о нём не было ни слова,
а то я могу приплести сюда что-нибудь ещё более неприглядное.
Например, перл, поскольку, судя по твоим сообщениям в форуме,
ты относишься к своему любимому лиспу, как "script kiddie."
---
"Я знаю правду! Все прежние правды --- прочь!"
---
...Я работаю антинаучным аферистом...
(defun join-strings (string-list delimiter)
(with-output-to-string (to)
(loop for x on string-list
do (princ (car x) to)
if (cdr x) do (princ delimiter to
Функцыональный (с reduce):
(defun join-strings (string-list delimiter)
(reduce (lambda (&optional a b)
(when a (concatenate 'string a delimiter b
string-list
CL-USER> (join-strings '("foo" "bar" "baz") "\\.")
"foo\\.bar\\.baz"
![](/images/graemlins/smile.gif)
Я читал "ANSI Common Lisp" Грехэма, а какие еще дельные книжки есть?
guile> (string-concatenate (cdr (apply append (map (lambda (elist "," e '("a" "b" "c"
"a,b,c"
---
...Я работаю антинаучным аферистом...
Я тебе разве этого не говорил?
Ничто не мешает спросить на freenode или c.l.lisp.
---
...Я работаю антинаучным аферистом...
Если человеку нужна программа, то пусть он пишет её сам.Че я по твоему весь Hyperspec наизусть должен знать? Если бы тогда у меня было бы больше времени, я бы вспомнил про функцию princ, которая делает то что надо. Но подобные провалы в памяти не мешают мне писать верный код, потому что всегда есть много способов достичь желаемого результата.
То, что "Common LISP" настолько неподъёмен, что даже ты,
будучи апологетом этого диалекта, не в курсе того, что именно
печатается в REPL (Иначе с чего бы тебе открывать это
определяя длину строки? показывает твоё знание языка.
Я читал "ANSI Common Lisp" Грехэма, а какие еще дельные книжки есть?Practical Common Lisp рулит.
>> То, что "Common LISP" настолько неподъёмен, что даже ты,
>> будучи апологетом этого диалекта, не в курсе того, что именно
>> печатается в REPL (Иначе с чего бы тебе открывать это
>> определяя длину строки? показывает твоё знание языка.
> Че я по твоему весь Hyperspec наизусть должен знать?
Нет.
Но элементарные вещи, к которым, в частности, относится
и семейство ваших "prin*", знать обязан. Это то же самое,
что знать, что такое "cadr".
> Если бы тогда у меня было бы больше времени, я бы
> вспомнил про функцию princ, которая делает то что надо.
Почему-то мне незнание SRFI наизусть не помешало найти
правильный способ склеивать строки.
> Но подобные провалы в памяти не мешают мне писать верный код,
> потому что всегда есть много способов достичь желаемого результата.
Ну-ну!
Сможешь показать, как _минуя_ "princ" достичь "желаемого результата",
заключающегося в выводе строки _как_она_есть_, а не
выворачивая внутренности, что более похоже на распечатку
памяти в отладчике?
---
...Я работаю антинаучным аферистом...
(use-modules (srfi srfi-1) (srfi srfi-13
(define (string-find s sub)
(or (string-contains s sub) (string-length s
(define (take-prefix pfx s)
(if (string-prefix? pfx s)
(string-take s (string-length pfx
(string-take s (string-find s pfx
(define (drop-prefix pfx s)
(string-drop s
(let posn (string-find s pfx
(if (zero? posn) (string-length pfx) posn
(define (string-break dlm s)
(unfold string-null?
(lambda (s) (take-prefix dlm s
(lambda (s) (drop-prefix dlm s
s
(write (string-break "<br>" "Left!<br>Left!<br>Left!"
(newline)
("Left!" "<br>" "Left!" "<br>" "Left!")
Действительно, сводится.
---
"Ведь согласитесь, какая прелесть
Мгновенно в яблочко попасть --- почти не целясь."
Ну-ну!Все функции вида prin* в конце-концов вызывают одну-единственную функцию write, которая умеет делать все.
Сможешь показать, как _минуя_ "princ" достичь "желаемого результата",
заключающегося в выводе строки _как_она_есть_, а не
выворачивая внутренности, что более похоже на распечатку
памяти в отладчике?
(write "\\aaaa" :escape nil)или
(let *print-escape* nil (write "\\aaaa"princ не является какой-то базовой функцией, обязательной для запоминания.
> (let *print-escape* nil (write
> princ не является какой-то базовой функцией, обязательной для запоминания.
Ты хочешь сказать, что для того, чтобы напечатать строку в человеческом виде,
надо изучать все параметры-ключи или управляющие переменные "write"?
Вообще-то, лисп изучают как высокоуровневый язык.
Помнится, ты мне указывал на то, что я пишу свои функции
вместо тех, которые даны SRFI-1. Сейчас ты утверждаешь,
что вместо простого вызова "princ", которого ты не нашёл,
ты бы пошёл изучать "write". Это, по крайней мере, есть
непоследовательно. Но ладно, допустим такое.
Тогда же ты утверждал, что, мол, ценность "Common" LISP
заключается в том, что _не_надо_ определять такие функции,
как в SRFI-1, поскольку они _уже_есть_в_языке_.
Сейчас мы все наблюдаем, как ты _не_нашёл_ простейшей
функции, которая не просто есть в языке, а есть даже
в куда более простом языке, каким является "Scheme".
Так что возникает вопрос: в чём заключается ценность "Common" LISP?
Пока что я вижу то, что описание языка неподъёмно
даже для его апологетов, что не так в случае схемы.
---
...Я работаю антинаучным аферистом...
>надо изучать все параметры-ключи или управляющие переменные "write"?
>Вообще-то, лисп изучают как высокоуровневый язык.
Ничего изучать не обязательно. Когда я пишу "write" в REPL, SLIME (Emacs-овый модуль для интерактивного программирования на Лиспе) выводит какие ключи у него есть. princ конечно тоже надо знать и в моем коде эта функция встречается очень часто. Но если забыл, всегда есть apropos, Hyperspec и функции, которые способны сделать то же самое (write).
>Сейчас мы все наблюдаем, как ты _не_нашёл_ простейшей
>функции, которая не просто есть в языке, а есть даже
>в куда более простом языке, каким является "Scheme".
И тем не менее я смог обойтись без этой функции. В парадигме There's Only One Way To Do It, если ты забыл функцию, то придется лазить в манах пока ее не найдешь. CL позволяет сразу переводить мысли в код, и неважно если ты знаешь 10% языка или 50%.
Базовые вещи CL можно выучить за 2 часа и начать писать программы. Scheme также можно выучить за 2 часа. Но проблема в том, что после месяца программирования на Scheme код будет выглядеть примерно также как после 2 часов, а CL-ер за это время научится писать более изящный и понятный код, используя встроенные функции.
>> Сейчас мы все наблюдаем, как ты _не_нашёл_ простейшей
>> функции, которая не просто есть в языке, а есть даже
>> в куда более простом языке, каким является "Scheme".
> И тем не менее я смог обойтись без этой функции.
> В парадигме There's Only One Way To Do It, если ты забыл
> функцию, то придется лазить в манах пока ее не найдешь.
> CL позволяет сразу переводить мысли в код, и неважно
> если ты знаешь 10% языка или 50%.
Теперь давай про то, как производить замену подстроки.
Пока что нас здесь трое: один общешептатель спрашивает,
как произвести замену подстроки, другой советует воспользоваться
перловыми РВ. Хочешь сказать, что это не "Only One Way"?
> Базовые вещи CL можно выучить за 2 часа и начать писать программы.
> Scheme также можно выучить за 2 часа. Но проблема в том,
> что после месяца программирования на Scheme код будет
> выглядеть примерно также как после 2 часов, а CL-ер за это
> время научится писать более изящный и понятный код,
> используя встроенные функции.
Очень спорно как вообще, так и в частности:
что-то я не заметил изящности кода замены подстроки ---
определение на двадцать с лишним строк в императивном
стиле с кучей сцеплений и сравнением через каждый знак.
Такое впечатление, что "Common" LISP не изобрёл даже
простейшей "string-contains" из SRFI-13.
---
...Я работаю антинаучным аферистом...
Does string s1 contain string s2? Return the index in s1 where s2 occurs as a substring, or false. The optional start/end indices restrict the operation to the indicated substrings.
Это же просто урезанный search, работающий только для строк! Интересно, для поиска в списках или массивах в Схеме тоже отдельные функции? Я думал в Схеме мало функций, а оказывается на одну функцию в CL приходится по крайней мере 3
![](/images/graemlins/shocked.gif)
Опять же --- возможна статическая проверка без загромождения языка.
К чему приводит загромождение языка, видно выше.
---
...Я работаю антинаучным аферистом...
Оставить комментарий
pilot
Хочется в сроке заменить все ' на \' и все \ на \\.Вообще, как заменить в строке подстроку?
На питоне — так:
Как сделать то же самое на Lisp'е?