lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Regexp Functions


From: Aaron Hill
Subject: Re: Regexp Functions
Date: Tue, 09 Jun 2020 14:40:35 -0700
User-agent: Roundcube Webmail/1.4.2

On 2020-06-09 12:42 am, Freeman Gilmore wrote:
I do no tthink this is what i want.   Let me try again  Say you have
"Xsdfghjkl"     If "x" is the first
character then replace the "g" if it exist with "Y" => "XsdYfhjkl"X

/(^A.*)B/ is the general pattern:

( ) Match the regex below and capture its match into backreference number 1.
  ^       Assert position at the beginning of a line.
   A      Match the character "A" literally.
    .*    Match any single character that is NOT a line break character
           between zero and unlimited times, as many times as possible,
           giving back as needed (greedy).
       B  Match the character "B" literally.

Since "A" and "B" above are literals, they may be replaced with "X" and "g", respectively, if that is what you wanted. Consider:

;;;;
(regexp-substitute/global #f
  "(^X.*)g"
  "Xsdfghjkl"
  'pre 1 "Y" 'post)
;;;;

====
"XsdfYhjkl"
====

Note that regular expressions can be a powerful tool [1], but they can also create more problems than they solve [2].

[1]: https://xkcd.com/208/
[2]: https://xkcd.com/1171/

Your original problem involved conditionally replacing a substring based on whether the string starts with a particular prefix. Consider:

;;;;
((lambda (s)
    (if (string-prefix? "X" s)
      (string-join (string-split s #\g) "Y")
      s))
   "Xsdfghjkl")
;;;;

====
"XsdfYhjkl"
====

In the above, we have separated the task into a few parts. First is checking the prefix of the string, as the absence of the desired text means no work needs to be done. When replacing, we use string-split and string-join to achieve our goal. This works because we are looking for a single character to replace.

A more general approach would need to use several of the string-* family of procedures:

;;;;
(define (string-find-replace s1 s2 s3)
  "Return the string @var{s1}, where all occurrences
of @var{s2} are replaced by @var{s3}."
  (let ((index (string-contains s1 s2)))
    (if (number? index)
      (string-append
        (string-take s1 index)
        s3
        (string-find-replace
          (string-drop s1 (+ index (string-length s2)))
          s2
          s3))
      s1)))
((lambda (s)
    (if (string-prefix? "XX" s)
      (string-find-replace s "gg" "YY")
      s))
   "XXssddffgghhjjkkll")
;;;;

====
"XXssddffYYhhjjkkll"
====

Hopefully you can see that in this situation, regexp-substitute/global becomes the more succinct way to express things:

;;;;
(regexp-substitute/global #f
  "(^XX.*)gg"
  "XXssddffgghhjjkkll"
  'pre 1 "YY" 'post)
;;;;

====
"XXssddffYYhhjjkkll"
====


-- Aaron Hill



reply via email to

[Prev in Thread] Current Thread [Next in Thread]