@@ -681,8 +681,8 @@ _free_pat_replacer(x) = nothing
681
681
_pat_replacer (x:: AbstractChar ) = isequal (x)
682
682
_pat_replacer (x:: Union{Tuple{Vararg{AbstractChar}},AbstractVector{<:AbstractChar},Set{<:AbstractChar}} ) = in (x)
683
683
684
- function replace (str :: String , pat_repl :: Vararg{Pair,N} ; count :: Integer = typemax (Int)) where N
685
- count == 0 && return str
684
+ # note: leave str untyped here to make it easier for packages like StringViews to hook in
685
+ function _replace_init (str, pat_repl :: NTuple{N, Pair} , count:: Int ) where N
686
686
count < 0 && throw (DomainError (count, " `count` must be non-negative." ))
687
687
n = 1
688
688
e1 = nextind (str, lastindex (str)) # sizeof(str)
@@ -697,11 +697,12 @@ function replace(str::String, pat_repl::Vararg{Pair,N}; count::Integer=typemax(I
697
697
r isa Int && (r = r: r) # findnext / performance fix
698
698
return r
699
699
end
700
- if all (> (e1), map (first, rs))
701
- foreach (_free_pat_replacer, patterns)
702
- return str
703
- end
704
- out = IOBuffer (sizehint= floor (Int, 1.2 sizeof (str)))
700
+ return patterns, replaces, rs, all (> (e1), map (first, rs))
701
+ end
702
+
703
+ # note: leave str untyped here to make it easier for packages like StringViews to hook in
704
+ function _replace_finish (out:: IO , str, count:: Int ,
705
+ patterns:: NTuple{N} , replaces:: NTuple{N} , rs:: NTuple{N} ) where N
705
706
while true
706
707
p = argmin (map (first, rs)) # TODO : or argmin(rs), to pick the shortest first match ?
707
708
r = rs[p]
@@ -737,12 +738,38 @@ function replace(str::String, pat_repl::Vararg{Pair,N}; count::Integer=typemax(I
737
738
end
738
739
foreach (_free_pat_replacer, patterns)
739
740
write (out, SubString (str, i))
740
- return String ( take! ( out))
741
+ return out
741
742
end
742
743
744
+ # note: leave str untyped here to make it easier for packages like StringViews to hook in
745
+ function _replace_io (out:: IO , retval, str, pat_repl:: Pair... ; count:: Integer = typemax (Int))
746
+ if count == 0
747
+ write (out, str)
748
+ return out
749
+ end
750
+ patterns, replaces, rs, notfound = _replace_init (str, pat_repl, count)
751
+ if notfound
752
+ foreach (_free_pat_replacer, patterns)
753
+ write (out, str)
754
+ return out
755
+ end
756
+ return _replace_finish (out, str, count, patterns, replaces, rs)
757
+ end
758
+
759
+ # note: leave str untyped here to make it easier for packages like StringViews to hook in
760
+ function _replace_str (str, pat_repl:: Pair... ; count:: Integer = typemax (Int))
761
+ count == 0 && return str
762
+ patterns, replaces, rs, notfound = _replace_init (str, pat_repl, count)
763
+ if notfound
764
+ foreach (_free_pat_replacer, patterns)
765
+ return str
766
+ end
767
+ out = IOBuffer (sizehint= floor (Int, 1.2 sizeof (str)))
768
+ return String (take! (_replace_finish (out, str, count, patterns, replaces, rs)))
769
+ end
743
770
744
771
"""
745
- replace(s::AbstractString, pat=>r, [pat2=>r2, ...]; [count::Integer])
772
+ replace([out::IO], s::AbstractString, pat=>r, [pat2=>r2, ...]; [count::Integer])
746
773
747
774
Search for the given pattern `pat` in `s`, and replace each occurrence with `r`.
748
775
If `count` is provided, replace at most `count` occurrences.
@@ -755,13 +782,21 @@ If `pat` is a regular expression and `r` is a [`SubstitutionString`](@ref), then
755
782
references in `r` are replaced with the corresponding matched text.
756
783
To remove instances of `pat` from `string`, set `r` to the empty `String` (`""`).
757
784
785
+ The return value is a new string after the replacements. If the `out::IO` argument
786
+ is supplied, the transformed string is instead written to `out` (returning `out`).
787
+ (For example, this can be used in conjunction with an [`IOBuffer`](@ref) to re-use
788
+ a pre-allocated buffer array in-place.)
789
+
758
790
Multiple patterns can be specified, and they will be applied left-to-right
759
791
simultaneously, so only one pattern will be applied to any character, and the
760
792
patterns will only be applied to the input text, not the replacements.
761
793
762
794
!!! compat "Julia 1.7"
763
795
Support for multiple patterns requires version 1.7.
764
796
797
+ !!! compat "Julia 1.10"
798
+ The `out::IO` argument requires version 1.10.
799
+
765
800
# Examples
766
801
```jldoctest
767
802
julia> replace("Python is a programming language.", "Python" => "Julia")
@@ -780,8 +815,18 @@ julia> replace("abcabc", "a" => "b", "b" => "c", r".+" => "a")
780
815
"bca"
781
816
```
782
817
"""
818
+ replace (out:: IO , s:: AbstractString , pat_f:: Pair... ; count= typemax (Int)) =
819
+ _replace_io (out, String (s), pat_f... , count= count)
820
+
783
821
replace (s:: AbstractString , pat_f:: Pair... ; count= typemax (Int)) =
784
- replace (String (s), pat_f... , count= count)
822
+ _replace_str (String (s), pat_f... , count= count)
823
+
824
+ # no copy needed for SubString{String}
825
+ replace (out:: IO , s:: SubString{String} , pat_f:: Pair... ; count= typemax (Int)) =
826
+ _replace_io (out, s, pat_f... , count= count)
827
+ replace (s:: SubString{String} , pat_f:: Pair... ; count= typemax (Int)) =
828
+ _replace_str (s, pat_f... , count= count)
829
+
785
830
786
831
# TODO : allow transform as the first argument to replace?
787
832
0 commit comments