Regex 正则表达式是如何匹配的?

Regex 正则表达式是如何匹配的?,regex,string,Regex,String,最近在一次采访中,我被问到一个问题,我有一个包含数十亿个字符的字符串。字符串中包含ASCII和非ASCII字符。任务是删除所有非ASCII字符,并且在输出中,字符串只能包含ASCII字符。解决方案必须是一种时间效率高的算法 我提出了两种方法: 制作一个ASCII字符数组。循环字符串检查当前字符是否在ASCII字符数组中。如果是,则跳过,否则将其替换为null。 显然,这不是一个省时的解决方案 其次,我建议如果我们把数组分成两半,再分成两半,依此类推。我仍然会像上面的方法一样检查ASCII字符。

最近在一次采访中,我被问到一个问题,我有一个包含数十亿个字符的字符串。字符串中包含ASCII和非ASCII字符。任务是删除所有非ASCII字符,并且在输出中,字符串只能包含ASCII字符。解决方案必须是一种时间效率高的算法

我提出了两种方法:

制作一个ASCII字符数组。循环字符串检查当前字符是否在ASCII字符数组中。如果是,则跳过,否则将其替换为null。 显然,这不是一个省时的解决方案

其次,我建议如果我们把数组分成两半,再分成两半,依此类推。我仍然会像上面的方法一样检查ASCII字符。 这次谈话引发了一场讨论,面试官正在寻找一种解决方案,我们不必逐字逐句地讨论,他建议使用正则表达式

我这里的问题是,当我们使用正则表达式匹配模式时,它会逐个字符检查字符串还是使用其他方法。我确信正则表达式将逐个字符查找/匹配。 谁能澄清我的疑问?
谢谢

您可以使用如下范围:

[\x20-\x7E]

此范围匹配从[space]到~的每个字符。可打印的ascii范围。

正则表达式确实在字符序列匹配的情况下使用了优化:简单解释一下,如果您正在寻找XXXXXXX,您知道您可以测试每个第7个字符,并且只有在找到X后才能仔细查看。但是,您需要过滤每一个字符:这意味着,正则表达式的效率不会更高,实际上也会更低,因为您需要进出regexp来处理您的发现

相反,假设类C架构的有效方法是从两个索引开始,源和结果为零,然后处理字符串:如果字符具有高位清除,则为ASCII:从源复制到结果,增加两个索引。如果设置了高位,则为非ASCII:只需增加源索引

void removeNonAscii(char *str) {
  int s, r;
  for (s = 0, r = 0; str[s]; s++) {
    if (!(str[s] & 128)) {
      str[r++] = str[s];
    }
  }
  str[r] = 0;
}

或者,您可以通过复制到一个新字符串而不是覆盖当前字符串来创建一个非破坏性字符串;算法是一样的。

是的,当然它需要检查每个字符。你怎么知道一个字符是ASCII码还是非ASCII码?顺便说一句,一个有几十亿个字符的字符串将消耗千兆字节的内存:你可能不想在内存中有这样一个字符串。ASCII字符就是一个值小于128的字符。@JBNizet,这就是我说的。位大小小于128的任何字符。但新行、制表符、回车符等字符也是ASCII码,但它们应该被丢弃。所以这意味着我们必须一个字符接一个字符,对吗?但像新行、制表符、回车符这样的字符也是ASCII码,但它们应该被丢弃。如果任务是保留所有ASCII字符,那就没有意义了。@Amadan,我想面试官对可打印的ASCII字符感兴趣。彼得·萨博正确地提到了这一点。我认为你的答案完全可以接受。例如,看看关于UTF-8编码的文章。第一个字节将告诉您它是ascii 1字节还是编码字符的2-4字节。例如,如果您正在处理一个中文文本,几乎所有的中文字符都有3个字节长,并且由于您可以从第一个字节看出这一点,因此您只需查看大约1/3的字节即可处理UTF-8编码的中文文本。请注意,还有其他与Unicode无关的中文文本编码,以及UTF-8以外的其他Unicode编码。定义范围或字符集不是这里的问题。这个模式是一个字符一个字符地检查整个字符串,还是我们有办法让我们的程序不必一个字符一个字符地检查?@SAM我想说必须检查每个字符,以检查它们是否在定义的范围内。是的,我认为你和Amadan的方法都是正确的。没有阅读价值,我们无法确定。再次感谢并加速我们可以在这里使用分区搜索类型的算法,对吗?你不能,因为你需要检查每个字符。