如何遍历字符串并替换某些短语?

Posted

技术标签:

【中文标题】如何遍历字符串并替换某些短语?【英文标题】:How do I iterate through a string and replace certain phrases? 【发布时间】:2016-01-05 13:30:53 【问题描述】:

我希望能够将诸如“you are”替换为“I am”以及将“your”替换为“my”之类的短语。如何在保持代码 DRY 的同时做到这一点?

到目前为止,我有类似的东西......

let re = Regex::new(r"you are").unwrap();
re.replace_all("you are awesome and so is your hat", "I am")

但这只会取代“你是”而不是“我的”部分。

我认为理想情况下它看起来像

let re = Regex::new(r"your|you are").unwrap();
re.replace_all("you are awesome and so is your hat", fn_with_pattern_matching)

【问题讨论】:

写两个单独的 replace_all 语句怎么样? 你最后一次使用fn_with_pattern_matching 的sn-p 应该是可行的。请参阅 regex 文档中的示例:doc.rust-lang.org/regex/regex/enum.Regex.html#examples-2 不过,您可能需要使用捕获组来确定要使用哪个文本作为替换。 @BurntSushi5,是的,我尝试过使用捕获组,但我在理解文档时遇到了很多麻烦,似乎无法让它按预期工作 @BurntSushi5 我认为该方法还需要我明确识别捕获索引号,如果我不知道字符串是否包含这些短语,这是不可取的 请edit你的问题表明你已经尝试过。 Stack Overflow 不是其他人为您编写代码的服务。向我们展示您为实现 fn_with_pattern_matching 而编写的内容,我们可以帮助实现这一目标。 【参考方案1】:

让我们从karthik manchala 回答和Shepmaster 建议开始:

将所有字符串放在一个数组中并遍历该数组。如果你的 应用程序逻辑是“将所有 A 替换为 B,然后将所有 C 替换为 D,然后 所有 E 和 F",那么代码将反映重复的逻辑。

我建议不要将字符串保存在数组中,而是将编译后的正则表达式存储在那里,以免每次都重新构建它们。

代码如下:

extern crate regex;

use regex::Regex;
use std::env::args;
use std::iter::FromIterator;

fn main() 
    let patterns = [("your", "mine"), ("you are", "I am")];
    let patterns = Vec::from_iter(patterns.into_iter().map(|&(k, v)| 
        (Regex::new(k).expect(&format!("Can't compile the regular expression: ", k)),
         v)
    ));
    for arg in args().skip(1) 
        println!("Argument: ", arg);
        for &(ref re, replacement) in patterns.iter() 
            let got = re.replace_all(&arg, replacement);
            if got != arg 
                println!("Changed to: ", got);
                continue;
            
        
    


就是这样,但为了完整起见,我想补充一点,如果您想要卓越的性能,那么您可以使用 PCRE 正则表达式引擎 (pcre crate) 中的 MARK 功能.

MARK 和这样的模式

"(?x) ^ (?:
    (*MARK:0) first pattern \
  | (*MARK:1) second pattern \
  | (*MARK:2) third pattern \
)"

您可以使用MARK 编号进行分类,或者在您的情况下作为带有替换的数组的索引。这通常比使用多个正则表达式更好,因为主题字符串只处理一次。

【讨论】:

“因为主题字符串只被处理一次”——这也改变了行为,对吗?例如,如果我替换 A -> BCB -> XY,那么创建多个循环与具有多个匹配项的单个循环将产生不同的结果。 @Shepmaster 这首先取决于循环是如何实现的以及正则表达式是什么。在某些情况下,行为是相同的,唯一的区别在于运行时成本。像往常一样,开发人员应该了解她在做什么。我在这里的目标不是写一本关于正则表达式MARK 及其所有细微差别的书,而是简单地提及这个有价值的工具。 ; )【参考方案2】:

您可以执行以下操作:

let str = "you are awesome and so is your hat";
let re = Regex::new(r"you are").unwrap();
let re1 = Regex::new(r"your").unwrap();
re.replace_all(str, "I am");
re1.replace_all(str, "my");

编辑:

如果您有很多短语要替换,请创建一个 ("phrase to replace", "phrase to replace with") 的映射并对其进行迭代以执行上述逻辑。

【讨论】:

感谢您的建议,但这不是很干燥,而且根本不能很好地扩展。我打算添加更多的短语来替换(例如“我”到“你”......等等) 但这不是很干 - 将所有字符串放在一个数组中并遍历该数组。如果您的应用程序逻辑是“将所有 A 替换为 B,然后将所有 C 替换为 D,然后将所有 E 替换为 F”,那么代码将反映该重复逻辑。

以上是关于如何遍历字符串并替换某些短语?的主要内容,如果未能解决你的问题,请参考以下文章

使用 int 变量编辑字符串短语 [关闭]

如何遍历数组并检查数组值

如何在mongodb中查找字符串(短语)的长度并根据长度对其进行排序?

MySQL 查询以检查某些短语(重复文章、抄袭)

如何使用 Perl 进行批量搜索和替换?

如何在 OpenOffice 中用另一个字符组合替换某些字符组合?