Добавить/исправить пунктуацию в php

Я медленно совершенствую функцию исправления пунктуации в PHP, которая используется для очистки пользовательского ввода. В настоящее время функция добавляет пробелы после знаков препинания, удаляет пробелы перед знаками препинания и делает первое слово каждого предложения заглавным. Я видел, как несколько человек искали аналогичную функцию, поэтому я рад поделиться тем, что у меня есть. Это довольно близко к тому, где я этого хочу, однако, когда он добавляет пробел после запятой, этого следует избегать, когда запятая находится внутри числа, такого как 1000. Может ли кто-нибудь предложить самый быстрый способ изменить мой код, чтобы игнорировать запятые внутри чисел ? Может быть, есть способы сократить то, что у меня есть, но при этом достичь того же результата? Спасибо за ваше время...

function format_punc($string){
    $punctuation = ',.;:';
    $string = str_replace(' ?', '?', str_replace(' .', '.', str_replace(' ,', ',', preg_replace('/(['.$punctuation.'])[\s]*/', '\1 ', $string))));
    $string = trim(preg_replace('/[[:space:]]+/', ' ', preg_replace('/([\.!\?]\s+|\A)(\w)/e', '"$1" . strtoupper("$2")', $string)));
    if($string[strlen($string)-1]==','){
        $string = substr($string, 0, -1).'.';
    }
    return $string;
}

person Tyler Mammone    schedule 25.08.2012    source источник
comment
Как вы можете быть уверены, что запятая является разделителем тысяч или имеете дело с перечислением чисел?   -  person Grampa    schedule 25.08.2012
comment
Вот почему я опубликовал это ... Я надеюсь, что кто-то может помочь продвинуть функцию, чтобы определить, имеет ли она дело с числами.   -  person Tyler Mammone    schedule 26.08.2012
comment
В некоторых странах используются разные делинеаторы для 1000, может быть, это можно угадать по настройкам ... (просто говорю)   -  person Cups    schedule 26.08.2012


Ответы (3)


Вот моя обновленная функция пунктуации php fix... Кажется, теперь она работает правильно. Я уверен, что есть способы сжать его, но он работает, чтобы сделать следующее со строкой...

Уменьшить повторяющиеся знаки препинания, такие как !! к !
Сократить несколько пробелов до одиночных
Удалить все пробелы перед ? . ,
Добавьте пробелы после ; :
Добавлять пробелы после запятых, но не тогда, когда они являются частью числа
Добавлять пробелы после точек, но не когда они являются частью числа или аббревиатуры
Удалять пробелы в начале и конце строки
Использовать заглавные буквы первое слово предложения
Изменить последний символ на точку, если это запятая

function format_punc($string){
    $punctuation = ';:';
    $spaced_punc = array(' ?', ' .', ' ,');
    $un_spaced_punc = array('?', '.', ',');
    $string = preg_replace("/([.,!?;:])+/iS","$1",$string);
    $string = preg_replace('/[[:space:]]+/', ' ', $string);
    $string = str_replace($spaced_punc, $un_spaced_punc, $string);
    $string = preg_replace('/(['.$punctuation.'])[\s]*/', '\1 ', $string);
    $string = preg_replace('/(?<!\d),|,(?!\d{3})/', ', ', $string);
    $string = preg_replace('/(\.)([[:alpha:]]{2,})/', '$1 $2', $string);
    $string = trim($string);
    $string = preg_replace('/([\.!\?]\s+|\A)(\w)/e', '"$1" . strtoupper("$2")', $string);
    if($string[strlen($string)-1]==','){
        $string = substr($string, 0, -1).'.';
    }
    return $string;
}

Если вы потратите время, чтобы сократить этот код и создать что-то, что по-прежнему возвращает те же результаты, поделитесь, пожалуйста! Спасибо и наслаждайтесь!

person Tyler Mammone    schedule 26.08.2012
comment
как вы защищаете знаки препинания в адресах электронной почты или URL-адресах? - person Baishu; 21.04.2015
comment
Для моего использования контент с адресами электронной почты или URL-адресами запрещается до того, как строка будет передана этой функции. Первоначально я написал это для форматирования строки после того, как она пройдет некоторые проверки на спам. Если вы измените его, чтобы правильно разрешать и форматировать электронные письма или URL-адреса в соответствии с вашими требованиями, поделитесь здесь своим улучшенным кодом для всех, кому это также может быть интересно. Спасибо. (у) - person Tyler Mammone; 22.04.2015
comment
Я использую другое решение. Я удаляю URL-адреса и электронные письма перед применением очистки и вставляю их обратно в конце. Не уверен, куда бы я поместил это в этой теме. - person Baishu; 22.04.2015
comment
Начиная с PHP 7 модификатор /e больше не поддерживается. - person stef; 25.02.2018

Я думаю, что регулярное выражение должно быть ([^0-9][.][^0-9])[\s]*

preg_replace('/([^0-9]['.$punctuation.'][^0-9])[\s]*/', '\1 ', $string)

Ссылка на тест регулярного выражения

person xCander    schedule 25.08.2012
comment
Спасибо, это близко... но это вызывает пробел, например... Строка, слово. 2000 - person Tyler Mammone; 26.08.2012

Это немного сложно, но это должно привести вас в правильном направлении:

<?php

// The following finds all commas in $string and identifies which comma is preceded and followed by a number

$string = 'Hello, my name, is John,Doe. I have 3,425 cats.';

function strpos_r($haystack, $needle)
{
    if(strlen($needle) > strlen($haystack))
        trigger_error(sprintf("%s: length of argument 2 must be <= argument 1", __FUNCTION__), E_USER_WARNING);

    $seeks = array();
    while($seek = strrpos($haystack, $needle))
    {
        array_push($seeks, $seek);
        $haystack = substr($haystack, 0, $seek);
    }
    return $seeks;
}

var_dump($commas = strpos_r($string, ',')); // gives you the location of all commas

for ($i = 0; i <= count($commas) - 1; $i++)
{
    if (is_numeric($commas[$i] - 1) && is_numeric($commas[$i] + 1)) 
    {
      // this means the characters before and after a given comma are numeric
      // don't add space (or delete the space) here

    }
}
person khaverim    schedule 25.08.2012