$ cat test.scm ; see reluctant-code-tags for usage (define (make-reluctant-processor tagspec outputopen outputclose) (let* ((tagnames (string-split tagspec #\space)) (tagor (string-join tagnames "|")) (regexpopen (make-regexp (string-append "\\[(" tagor ")\\]"))) (table (make-hash-table))) (for-each (lambda (s) (hash-set! table s (make-regexp (string-append "\\[/" s "\\]")))) tagnames) (letrec ((outside (lambda (s outlistrev) (let ((m (regexp-exec regexpopen s))) (if m (inside (match:suffix m) (cons* (match:substring m) (match:prefix m) outlistrev) (match:substring m 1)) (string-concatenate-reverse outlistrev s))))) (inside (lambda (s outlistrev open) (let ((m (regexp-exec (hash-ref table open) s))) (if m (outside (match:suffix m) (cons* outputclose (match:prefix m) outputopen (cdr outlistrev))) (string-concatenate-reverse outlistrev s)))))) (lambda (s) (outside s '()))))) (define reluctant-code-tags (make-reluctant-processor "codeblock code c" "
" "
")) $ guile -l test.scm GNU Guile 2.2.3 [...] scheme@(guile-user)> (reluctant-code-tags "a [code]1[/code] [code]2[/code] b") $1 = "a
1
2
b" scheme@(guile-user)> (reluctant-code-tags "a [codeblock][code]1[/code][/codeblock] b [code]2[/code] c") $2 = "a
[code]1[/code]
b
2
c" scheme@(guile-user)>