4

好的,我希望有人可以用一点正则表达式来帮助我。

我正在尝试清理字符串。

基本上,我是:

  1. 用替换替换除 A-Za-z0-9 之外的所有字符。

  2. 用单个替换实例替换替换的连续副本。

  3. 从字符串的开头和结尾修剪替换。

示例输入:

( && (%()$( )#& #&%&% %(%$ +-_狗跳过原木*(&)$%& )#)@#%&)&^)@# )

所需输出:

The+dog+jumped+over+the+log

我目前正在使用这个非常混乱的代码,并且只知道有一种更优雅的方式来完成这个......

function clean($string, $replace){

    $ok = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    $ok .= $replace;
    $pattern = "/[^".preg_quote($ok, "/")."]/";

    return trim(preg_replace('/'.preg_quote($replace.$replace).'+/', $replace, preg_replace($pattern, $replace, $string)),$replace);
}

Regex-Fu 大师能否为我提供更简单/更有效的解决方案?


Botond Balázs 和 hakre 提出并解释了一个更好的解决方案:

function clean($string, $replace, $skip=""){
    // Escape $skip
    $escaped = preg_quote($replace.$skip, "/");

    // Regex pattern
    // Replace all consecutive occurrences of "Not OK" 
    // characters with the replacement
    $pattern = '/[^A-Za-z0-9'.$escaped.']+/';

    // Execute the regex
    $result = preg_replace($pattern, $replace, $string);

    // Trim and return the result
    return trim($result, $replace);
}
4

2 回答 2

2

我不是“正则表达式忍者”,但我会这样做。

function clean($string, $replace){
    /// Remove all "not OK" characters from the beginning and the end:
    $result = preg_replace('/^[^A-Za-z0-9]+/', '', $string);
    $result = preg_replace('/[^A-Za-z0-9]+$/', '', $result);

    // Replace all consecutive occurrences of "not OK" 
    // characters with the replacement:
    $result = preg_replace('/[^A-Za-z0-9]+/', $replace, $result);

    return $result;
}

我想这可以进一步简化,但是在处理正则表达式时,清晰度和可读性通常比聪明或编写超级优化代码更重要。

让我们看看它是如何工作的:

  • /^[^A-Za-z0-9]+/
    • ^匹配字符串的开头。
    • [^A-Za-z0-9]匹配所有字母数字字符
    • +意思是“匹配前面的一个或多个”
  • /[^A-Za-z0-9]+$/
    • 和上面一样,除了$匹配字符串的结尾
  • /[^A-Za-z0-9]+/
    • 和上面一样,除了它也匹配中间字符串

编辑: OP 是正确的,前两个可以替换为trim()

function clean($string, $replace){
    // Replace all consecutive occurrences of "not OK" 
    // characters with the replacement:
    $result = preg_replace('/[^A-Za-z0-9]+/', $replace, $result);

    return trim($result, $replace);
}
于 2012-11-18T10:37:44.327 回答
2

我不想听起来超级聪明,但我不会称它为 regex-foo。

您所做的实际上几乎是正确的方向,因为您使用preg_quote,许多其他人甚至不知道该功能。

但是可能在错误的地方。错误的地方,因为您引用了字符类中的字符,并且在正则表达式中引用了(相似但)不同的规则。

此外,正则表达式的设计考虑了您的情况。这可能是您寻找向导的部分,让我们看看一些选项如何使您的否定字符类更紧凑(我将生成保留以使其更明显):

[^0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]

有类似0-9,A-Z的结构a-z,可以准确地表示这一点。如您所见-,它是字符类中的一个特殊字符,它不是字面意思,而是具有一些从到到的字符:

[^0-9A-Za-z]

所以这已经更紧凑并且代表相同。还有像\d\w这样的符号在你的情况下可能很方便。但我暂时采用第一个变体,因为我认为它的作用已经很明显了。

另一部分是重复。让我们看看,有+哪个意味着一个或多个。所以你想替换一个或多个不匹配的字符。您可以通过在应该匹配一次或多次的部分末尾添加它来使用它(默认情况下它是贪婪的,因此如果有 5 个字符,则将采用这 5 个字符,而不是 4 个):

[^0-9A-Za-z]+

我希望这是有帮助的。另一个步骤是在开头和结尾也删除不匹配的字符,但现在是清晨,我对此不太熟悉。

于 2012-11-18T10:38:07.687 回答