From 1ad4fbd841abb9ced7a6b1225fe309acb27f5def Mon Sep 17 00:00:00 2001 From: penguindark <57967770+penguindark@users.noreply.github.com> Date: Mon, 3 Jan 2022 05:32:24 +0100 Subject: [PATCH] regex: add a replace_n function (#13016) --- vlib/regex/README.md | 10 ++++++++++ vlib/regex/regex_test.v | 19 +++++++++++++++++++ vlib/regex/regex_util.v | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/vlib/regex/README.md b/vlib/regex/README.md index 33a6de5525..067f17d802 100644 --- a/vlib/regex/README.md +++ b/vlib/regex/README.md @@ -604,6 +604,16 @@ to use a quick function: pub fn (mut re RE) replace_simple(in_txt string, repl string) string ``` +If it is needed to replace N instances of the found strings it is possible to use: +```v ignore +// replace_n return a string where the firts `count` matches are replaced with the repl_str string +// `count` indicate the number of max replacements that will be done. +// if count is > 0 the replace began from the start of the string toward the end +// if count is < 0 the replace began from the end of the string toward the start +// if count is 0 do nothing +pub fn (mut re RE) replace_n(in_txt string, repl_str string, count int) string +``` + #### Custom replace function For complex find and replace operations, you can use `replace_by_fn` . diff --git a/vlib/regex/regex_test.v b/vlib/regex/regex_test.v index 8f479b757b..92d911cbd4 100644 --- a/vlib/regex/regex_test.v +++ b/vlib/regex/regex_test.v @@ -623,6 +623,25 @@ fn test_regex_func_replace(){ assert result == txt2 } +fn rest_regex_replace_n(){ + s := "dario 1234 pepep 23454 pera" + query := r"\d+" + + mut re := regex.regex_opt(query) or { panic(err) } + + assert re.replace_n(s, "[repl]", 0) == "dario 1234 pepep 23454 pera" + assert re.replace_n(s, "[repl]", -1) == "dario 1234 pepep [repl] pera" + assert re.replace_n(s, "[repl]", 1) == "dario [repl] pepep 23454 pera" + assert re.replace_n(s, "[repl]", 2) == "dario [repl] pepep [repl] pera" + assert re.replace_n(s, "[repl]", -2) == "dario [repl] pepep [repl] pera" + assert re.replace_n(s, "[repl]", 3) == "dario [repl] pepep [repl] pera" + assert re.replace_n(s, "[repl]", -3) == "dario [repl] pepep [repl] pera" + + //mut res := re.replace_n(s, "[repl]", -1) + //println("source: ${s}") + //println("res : ${res}") +} + // test quantifier wrong sequences const( test_quantifier_sequences_list = [ diff --git a/vlib/regex/regex_util.v b/vlib/regex/regex_util.v index 02853ced95..2cb84a51d1 100644 --- a/vlib/regex/regex_util.v +++ b/vlib/regex/regex_util.v @@ -463,3 +463,37 @@ pub fn (mut re RE) replace(in_txt string, repl_str string) string { } return res.str() } + +// replace_n return a string where the firts count matches are replaced with the repl_str string, +// if count is > 0 the replace began from the start of the string toward the end +// if count is < 0 the replace began from the end of the string toward the start +// if count is 0 do nothing +pub fn (mut re RE) replace_n(in_txt string, repl_str string, count int) string { + mut i := 0 + mut index := 0 + mut i_p := 0 + mut res := strings.new_builder(in_txt.len) + mut lst := re.find_all(in_txt) + + if count < 0 { // start from the right of the string + lst = lst#[count * 2..] // limitate the number of substitions + } else if count > 0 { // start from the left of the string + lst = lst#[..count * 2] // limitate the number of substitions + } else if count == 0 { // no replace + return in_txt + } + + // println("found: ${lst}") + for index < lst.len { + i = lst[index] + res.write_string(in_txt[i_p..i]) + res.write_string(repl_str) + index++ + i_p = lst[index] + index++ + } + i = i_p + res.write_string(in_txt[i..]) + + return res.str() +}