繁体   English   中英

正则表达式删除除表情符号以外的所有非字母数字字符

[英]regex remove all non alphanumeric characters except emoticons

我需要删除除空格和允许表情符号之外的所有非字母数字字符。

允许的表情符号是:):( :P等(最受欢迎)。

我有一个字符串:

$string = 'Hi! Glad # to _ see : you :)';

所以我需要处理这个字符串并获得以下内容:

$string = 'Hi Glad to see  you :)';

另外请注意表情符号可以包含空格

例如

而不是:)):

要么

:P代替:P

有人有这个功能吗?

如果有人帮助过我会很棒:)

UPDATE

非常感谢您的帮助。

巴克利提供现成的解决方案

但如果字符串包含带空格的表情符号

嗨! 很高兴见到你 : )

结果等于嗨很高兴见到你

正如你看到的表情:)被切断。

我不“说”php;)但这是在JS中做到的。 也许你可以转换它。

var sIn = 'Hi! Glad # to _ see : you :)',
    sOut;

sOut = sIn.match(/([\w\s]|: ?\)|: ?\(|: ?P)*/g).join('');

它在您尝试的其他方面起作用 - 它找到所有“合法”字符/组合并将它们连接在一起。

问候

编辑:更新了正则表达式以处理表情符号中的可选空格(如前面所述)。

哈! 这个很有意思

更换

(?!(:\)|:\(|:P))[^a-zA-Z0-9 ](?<!(:\)|:\(|:P))

什么都没有

我们的想法是,你使用相同的正则表达式将非法字符夹在一次作为负面看起来,而将其作为负面看起来。

结果将包含连续的空格。 这是正则表达式无法在1次扫描AFAIK中执行的操作,因为它无法同时查看多个匹配项。

要消除连续的空格,可以用\\s+替换\\s+ (一个空的空间)

这是一个更新的答案,符合表情符号可以包含空格的新要求

更换

((:\))|(:\()|(:P)|(: \))|: P)|[^0-9a-zA-Z\r\n ]

$1

在自由间隔模式下格式化成为

(?x)
(
  (?::\))|
  (?::\()|
  (?::P)|
  (?::\ \))|
  :\ P
)|
[^0-9a-zA-Z\r\n ]

在PHP中

$result = preg_replace('/((:\))|(:\()|(:P)|(: \))|: P)|[^0-9a-zA-Z\r\n ]/', '$1', $subject);

我们的想法是,我们使用包含多个字符的表情符号启动正则表达式,这些表情符号可以包含非法字符。

该组被捕获,后来用作替换$ 1

然后,在交替之后,我们使用我们否定的字符白名单,因此它将被匹配,但在替换的模式中将不会被提及。

所有不匹配的东西(我们的白名单)将按照惯例在结果中重复。

关于没有的事情是在列出可能妨碍性能的表情符号时有很多分组。 为了防止这种情况,我们可以使正则表达式更冗长:

 ((?::\))|(?::\()|(?::P)|(?:: \))|: P)|[^0-9a-zA-Z\r\n ]

多个连续空间保留,并且无法在1次扫描AFAIK中求解。

这是一个字符串格式化程序,可以完成这项工作,假设表情符号通常为2个字符长:

<?php

class StringFormatter
{
  private $blacklist;
  private $whitelist;

  public function __construct(array $blacklist, array $whitelist)
  {
    $this->blacklist = $blacklist;
    $this->whitelist = $whitelist;
  }

  public function format($str)
  {
    $strLen = strlen($str);

    $result = '';
    $counter = 0;
    while ($counter < $strLen) {
      // get a character from the string
      $char = substr($str, $counter, 1);

      // if not blacklisted, allow it in the result
      if (!in_array($char, $this->blacklist)) {
        $result .= $char;
        $counter++;
        continue;
      }

      // if we reached the last letter, break out of the loop
      if ($counter >= $strLen - 1) {
        break;
      }

      // we assume all whitelisted entries have same length (e.g. 2
      // for emoticons)
      if (in_array(substr($str, $counter, 2), $this->whitelist)) {
        $result .= substr($str, $counter, 2);
        $counter += 2;
      } else {
        $counter++;
      }
    }

    return $result;
  }
}

// example usage
// $whitelist is not the entire whitelist, actually it's the exceptions
// to the blacklist, so more complext strings including blacklisted  characters that should be allowed
$formatter = new StringFormatter(['#', '_', ':', '!'], [':)', ':(']);
echo $formatter->format('Hi! Glad # to _ see : you :)');

上面的代码可以进一步重构为更清晰,但你得到的图片。

我用这个正则表达式,

(?i)(:\s*[)p(])(*SKIP)(*FAIL)|[^a-z0-9 ]

演示: https//regex101.com/r/nW6iL3/2

PHP用法:

$string = ':     ) instead of :)

or

:     P instead of :P

Hi! Glad # to _ see : you :)';

echo preg_replace('~(?i)(:\s*[)p(])(*SKIP)(*FAIL)|[^a-z0-9 ]~', '', $string);

输出:

:)而不是:)或:P代替:PHi很高兴见到你:)

演示: https//eval.in/416394

如果表情符号的结束部分发生变化,或者您有其他表情符号,则可以将其添加到此字符类[)p(]

您还可以通过将:更改为角色类来改变眼睛,这样您就可以做到

(?i)([:;]\s*[)p(])(*SKIP)(*FAIL)|[^a-z0-9 ] 

如果你也想允许眨眼的脸(我认为分号是眨眼)..

更新

一点一点解释......

(?i) =使正则表达式不敏感

: =寻找眼睛(冒号)

\\s* =搜索零或更多(*是前面字符的0或更多)空格字符( \\h在这里可能更好, \\s包括新行和制表符)

[)p(] =这是一个允许其中任何字符出现的字符类.so )p(允许在这里允许)。

(*SKIP)(*FAIL) =如果我们发现之前的正则表达式忽略了它,www.rexegg.com / regex-best -trick.html。

| =或

[^a-z0-9 ] - 一个否定的字符类,表示此列表中没有的任何字符。

regex101还有正则表达式的文档。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM