PHP:如何从指定索引提取子字符串,直到下一个空格或行尾

PHP:如何从指定索引提取子字符串,直到下一个空格或行尾,php,regex,Php,Regex,我有一个输入字符串: $subject=“这个标点符号!还有这个标点符号。不要给那个标点符号留空格。” 我还有一个数组,其中包含我希望执行的替换的例外情况,目前有一个成员: $exceptions = array( 0 => "n't" ); 我之所以要实现这个复杂的解决方案,是因为这个数组将来将被扩展,并且可能包含数百个成员 我想在单词边界插入空格(重复的空格将在以后删除)。不过,某些界限应该被忽略。例如,上面句子中的感叹号和句号应该用空格括起来,但撇号不应该用

我有一个输入字符串:

$subject=“这个标点符号!还有这个标点符号。不要给那个标点符号留空格。”

我还有一个数组,其中包含我希望执行的替换的例外情况,目前有一个成员:

$exceptions = array(
  0 => "n't"
);
我之所以要实现这个复杂的解决方案,是因为这个数组将来将被扩展,并且可能包含数百个成员

我想在单词边界插入空格(重复的空格将在以后删除)。不过,某些界限应该被忽略。例如,上面句子中的感叹号和句号应该用空格括起来,但撇号不应该用空格括起来。一旦使用
trim(preg_replace('/\s+/','.$subject))从最终结果中删除重复的空格,它应该如下所示:

“这个标点符号!还有这个标点符号。那个标点符号没有空格。”

我正在制定以下解决方案:

  • 使用
    preg_匹配('\b',$subject,$OFFSET,'preg_OFFSET_CAPTURE')
    收集可插入空格的索引数组

  • 迭代
    $offset
    数组

    • $subject
      从当前偏移量之前的空格分割到下一个空格或行尾
    • 检查拆分结果是否包含在
      $exceptions
      数组中
    • 若拆分结果不包含在异常数组中,请在当前偏移量处插入空白字符
    到目前为止,我有以下代码:

    $subject="This punctuation! And this one. Does n't space that one.";
    $pattern = '/\b/';
    preg_match($pattern, $subject, $offsets, PREG_OFFSET_CAPTURE );
    
    if(COUNT($offsets)) {
      $indexes = array();
      for($i=0;$i<COUNT($offsets);$i++) {
        $offsets[$i];
        $substring = '?';
    
        // Replace $substring with substring from after whitespace prior to $offsets[$i] until next whitespace...
    
        if(!array_search($substring, $exceptions)) {
          $indexes[] = $offsets[$i];
        }
      }
    
      // Insert whitespace character at each offset stored in $indexes...
    
    }
    
    $subject=“这个标点符号!还有这个标点符号。不要给那个标点符号留空格。”;
    $pattern='/\b/';
    预匹配($pattern,$subject,$OFFSET,预偏移捕获);
    如果(计算($offset)){
    $index=array();
    对于($i=0;$i一个“简单”(但不一定快,取决于有多少异常)的解决方案是首先用不包含任何标点符号的唯一字符串替换字符串中的所有异常,然后执行替换,然后将唯一替换字符串转换回其原始版本

    下面是一个使用
    md5
    的示例(但可能还有很多其他内容):

    一个“简单”(但不一定快,取决于有多少异常)的解决方案是,首先用不包含任何标点符号的唯一字符串替换字符串中的所有异常,然后执行替换,然后将唯一替换字符串转换回其原始版本

    下面是一个使用
    md5
    的示例(但可能还有很多其他内容):


    为什么说
    没有空格。
    ,但还是用空格隔开了?怎么样:
    $res=preg\u replace(“/(?撇号没有空格。我实际上犯了一个错误,只是更新了它。应该是
    而不是空格。
    …因此结尾处的句号是空格,但撇号不是空格,因为它属于
    不匹配,是
    $exceptions
    数组的一部分。@Toto这只适用于特定字符。我需要稍后结束
    $exceptions
    数组,以可能包含数百个成员…因此,我将仅对该数组进行匹配,而不是尝试创建一个满足所有成员的正则表达式。为什么说
    不将该数组隔开。
    ,但仍将其隔开?如何:
    $res=preg\u replace(“/(?撇号没有空格。我实际上犯了一个错误,只是更新了它。应该是
    而不是空格。
    …因此结尾处的句号是空格,但撇号不是空格,因为它属于
    不匹配,是
    $exceptions
    数组的一部分。@Toto这只适用于特定字符。我需要稍后结束
    $exceptions
    数组,使其可能包含数百个成员…因此,我将只匹配该数组,而不是尝试创建一个满足所有成员的正则表达式。非常高兴++这个答案大大超出了我的预期。非常感谢!@Thefourthbird:谢谢;)@乔舒亚·弗劳德:不客气,很高兴能帮上忙。总是很高兴++这个答案大大超出了我的预期。非常感谢!@Thefourthbird:谢谢;)@JoshuaFlood:不客气,很高兴能帮上忙。
    $subject = "This punctuation! And this one. Doesn't space that one.";
    
    $exceptions = ["n't"];
    
    foreach ($exceptions as $exception) {
        $result = str_replace($exception, md5($exception), $subject);
    }
    
    $result = preg_replace('/[^a-z0-9\s]/i', ' \0', $result);
    
    foreach ($exceptions as $exception) {
        $result = str_replace(md5($exception), $exception, $result);
    }
    
    echo $result;  // This punctuation ! And this one . Doesn't space that one .
    
    $res = preg_replace("/(?:n't|ALL EXCEPTIONS PIPE SEPARATED)(*SKIP)(*F)|(?!^)(?<!\h)\b(?!\h)/", " ", $subject);
    echo $res;
    
    This punctuation ! And this one . Doesn't space that one .