replace-first

added
1.2

ns
clojure.string

type
function

(replace-first s match replacement)

Replaces the first instance of match with replacement in s.

match/replacement can be:

char / char
string / string
pattern / (string or function of match).

See also replace.

The replacement is literal (i.e. none of its characters are treated
specially) for all cases above except pattern / string.

For pattern / string, $1, $2, etc. in the replacement string are
substituted with the string that matched the corresponding
parenthesized group in the pattern.  If you wish your replacement
string r to be used literally, use (re-quote-replacement r) as the
replacement argument.  See also documentation for
java.util.regex.Matcher's appendReplacement method.

Example:
(clojure.string/replace-first "swap first two words"
#"(\\w+)(\\s+)(\\w+)" "$3$2$1")
-> "first swap two words"

                user=> (use '[clojure.string :only (replace-first)])

;; Only replace the first match.
user=> (replace-first "A good day to you, sir.  Good day." #"day" "night")
"A good night to you, sir.  Good day."

;; If there are no matches, return the original string.
user=> (replace-first "A good day to you, sir." #"madam" "master")
"A good day to you, sir."

;; (?i) at the beginning of a pattern makes the entire thing match
;; case-insensitively, at least for US ASCII characters.  (?u) does
;; the corresponding thing for Unicode.
user=> (replace-first "Day need not be SHOUTED." #"(?i)day" "night")
"night need not be SHOUTED."

;; See here for many details on regex patterns:
;; http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
;; Also the book "Mastering Regular Expressions" by Jeffrey Friedl.

            
                user=> (use '[clojure.string :only (replace-first)])

;; Pattern matches from beginning of string (signified by ^) up to the
;; last occurrence of /, because by default * is greedy, i.e. it
;; matches as much as possible.
user=> (replace-first "/path/to/file/name" #"^.*/" "")
"name"

;; Use *? to match as little as possible.
user=> (replace-first "/path/to/file/name" #"^.*?/" "")
"path/to/file/name"

            
                ;; Note: When replace-first or replace have a regex pattern as their
;; match argument, dollar sign ($) and backslash (\\) characters in
;; the replacement string are treated specially.

;; Example: pattern matches string "fodder", with (o+) matching "o"
;; and (\\S+) matching "dder".  Replacement string says to replace the
;; entire match "fodder" with $2, the string matched by the second
;; parenthesized group, "dder", followed by $1, "o".
user=> (str/replace-first "fabulous fodder foo food" #"f(o+)(\\S+)" "$2$1")
"fabulous ddero foo food"

;; To avoid this special treatment of $ and \\, you must escape them with
;; \\.  Because it is in a Clojure string, to get one \\ we must escape
;; *that* with its own \\.
user=> (str/replace-first "fabulous fodder foo food" #"f(o+)(\\S+)" "\\\\$2\\\\$1")
"fabulous $2$1 foo food"

;; To ensure the replacement is treated literally, call
;; java.util.regex.Matcher/quoteReplacement on it.  A shorter name
;; like re-qr can be handy.
user=> (import '(java.util.regex Matcher))
java.util.regex.Matcher

user=> (defn re-qr [replacement]
         (Matcher/quoteReplacement replacement))
#'user/re-qr

user=> (str/replace-first "fabulous fodder foo food" #"f(o+)(\\S+)" (re-qr "$2$1"))
"fabulous $2$1 foo food"

            
                ;; Note: See clojure.core/subs for discussion of behavior of substrings
;; holding onto references of the original strings, which can
;; significantly affect your memory usage in some cases.