diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi index 0ea49485f..ede16de64 100644 --- a/doc/ref/api-data.texi +++ b/doc/ref/api-data.texi @@ -4227,6 +4227,22 @@ a predicate, if it is a character, it is tested for equality and if it is a character set, it is tested for membership. @end deffn +The following additional functions are available in the module @code{(ice-9 string-fun)}. They can be used with: + +@example +(use-modules (ice-9 string-fun)) +@end example + +@deffn {Scheme Procedure} string-replace-substring str substring replacement +Return a new string where every instance of @var{substring} in string +@var{str} has been replaced by @var{replacement}. For example: + +@lisp +(string-replace-substring "a ring of strings" "ring" "rut") +@result{} "a rut of struts" +@end lisp +@end deffn + @node Representing Strings as Bytes @subsubsection Representing Strings as Bytes diff --git a/module/ice-9/string-fun.scm b/module/ice-9/string-fun.scm index c27ff847f..03e0238fa 100644 --- a/module/ice-9/string-fun.scm +++ b/module/ice-9/string-fun.scm @@ -25,13 +25,17 @@ separate-fields-discarding-char separate-fields-after-char separate-fields-before-char string-prefix-predicate string-prefix=? sans-surrounding-whitespace sans-trailing-whitespace - sans-leading-whitespace sans-final-newline has-trailing-newline?)) + sans-leading-whitespace sans-final-newline has-trailing-newline? + string-replace-substring)) ;;;; ;;; ;;; Various string funcitons, particularly those that take ;;; advantage of the "shared substring" capability. +;;; FIXME Document these functions in Miscellaneous String Operations:: +;;; in doc/ref/api-data.texi. ;;; + ;;; {String Fun: Dividing Strings Into Fields} ;;; @@ -278,3 +282,34 @@ ;;; (fail parts) ;;; (apply return parts)))) + + +;;; {String Fun: string-replace-substring} +;;; + +;; string-replace-substring By A. Wingo in +;; https://lists.gnu.org/archive/html/guile-devel/2014-03/msg00058.html +;; also in string-replace-substring guix:guix/utils.scm. + +(define (string-replace-substring str substring replacement) + "Return a new string where every instance of @var{substring} in string + @var{str} has been replaced by @var{replacement}. For example: + + @lisp + (string-replace-substring \"a ring of strings\" \"ring\" \"rut\") + @result{} \"a rut of struts\" + @end lisp + " + (let ((sublen (string-length substring))) + (with-output-to-string + (lambda () + (let lp ((start 0)) + (cond + ((string-contains str substring start) + => (lambda (end) + (display (substring/shared str start end)) + (display replacement) + (lp (+ end sublen)))) + (else + (display (substring/shared str start))))))))) + diff --git a/test-suite/tests/strings.test b/test-suite/tests/strings.test index 32c9b9ef3..52b3dd034 100644 --- a/test-suite/tests/strings.test +++ b/test-suite/tests/strings.test @@ -20,7 +20,8 @@ (define-module (test-strings) #:use-module ((system base compile) #:select (compile)) - #:use-module (test-suite lib)) + #:use-module (test-suite lib) + #:use-module (ice-9 string-fun)) (define exception:read-only-string (cons 'misc-error "^string is read-only")) @@ -693,3 +694,9 @@ (string-upcase! (substring/shared str2 1 4)) (and (string=? str1 "foofoofoo") (string=? str2 "oFOOf"))))) + +(with-test-prefix "miscellaneous string functions" + + (pass-if "string-replace-substring" + (string=? (string-replace-substring "a ring of strings" "ring" "rut") + "a rut of struts")))