We can search for a value in a string and replace it with another value using the clojure.string/replace
function. The first parameter is the original string value that we want to replace parts of. The second parameter can be a string value or regular expression. The last parameter is the replacement value that can be a string value or a function that returns a string value. The function itself gets either a string argument if the match has no nested groups (when match is a regular expression) or a vector with a complete match followed by the nested groups when the match has nested groups.
In the following example we several invocation of the clojure.string/replace
function with different arguments:
(ns mrhaki.string.replace (:require [clojure.string :as str] [clojure.test :refer [is]])) ;; Example string value to do replacements on. (def s "Programming with Clojure is fun!") ;; Match argument can be a string value, ;; that gives same result as java.lang.String#replace method. (is (= "Programming with Clojure is awesome!" (str/replace s "fun" "awesome") (.replace s "fun" "awesome"))) ;; Match argument can also be regular expression pattern. (is (= "Programming_with_Clojure_is_fun!" (str/replace s #"\s+" "_"))) ;; When the regular expression pattern has groups ;; we can refer to them using $ followed by matched ;; group number, eg. $1 for the first group. (is (= "Execution 1 took 200ms" (str/replace "run1=200ms" #"run(\d+)=(\d+ms)" "Execution $1 took $2"))) ;; Replace argument can be a function. ;; Argument of the function is string of entire match ;; if there are no nested groups. (is (= "[NOTE] [CAUTION]" (str/replace "[note] [caution]" #"\[\w+\]" #(.toUpperCase %)))) ;; Otherwise if there are nested groups a vector is ;; used as argument for the replacment function ;; where the first argument is the ;; entire match followed by the nested groups. (is (= "ABC def" (str/replace "abc DEF" #"(\w+)(\s+)(\w+)" #(str (.toUpperCase (% 1)) (% 2) (.toLowerCase (% 3)))))) ;; By destructuring the vector argument ;; we can refer to the groups using a name. (defn replacement [[_ execution time]] (let [seconds (/ (bigdec time) 1000)] (str "Execution " execution " took " seconds " seconds"))) (is (= "Execution 1 took 0.2 seconds" (str/replace "run1=200ms" #"run(\d+)=(\d+)ms" replacement)))
Written with Clojure 1.10.1.