2

これは文章サニタイザーです。

function sanitize_sentence($string) {
    $pats = array(
    '/([.!?]\s{2}),/',      # Abc.  ,Def
    '/\.+(,)/',             # ......,
    '/(!|\?)\1+/',          # abc!!!!!!!!, abc?????????
    '/\s+(,)/',             # abc   , def
    '/([a-zA-Z])\1\1/');    # greeeeeeen
    $fixed = preg_replace($pats,'$1',$string); # apply pats
    $fixed = preg_replace('/(?:(?<=\s)|^)[^a-z0-9]+(?:(?=\s)|$)/i', '',$fixed); # bad chunks
    $fixed = preg_replace( '/([!?,.])(\S)/', '$1 $2', $fixed); # spaces after punctuation, if it doesn't exist already
    $fixed = preg_replace( '/[^a-zA-Z0-9!?.]+$/', '.', $fixed); # end of string must end in period
    $fixed = preg_replace('/,(?!\s)/',', ',$fixed); # spaces after commas
    return $fixed;
}

これはテスト文です:

こんにちは [[[[[[]]]]]] 友達……?元気ですか [}}}}}}

次のように返されます。

こんにちは友達……?元気ですか

しかし、代わりにそれが返されます:

こんにちは友人。.. .. ? 元気ですか。

したがって、2つの問題があり、それらの周りの解決策が見つかりません:

  1. ピリオドのセットは「.. ..」に分割されています。何らかの理由で。疑問符の横に「.....」のままにしておく必要があります。
  2. 文字列のどこかに !?,のいずれかの文字が少なくとも 1 つある場合にのみ、文字列の最後はピリオドで終了する必要があります。(これらの文字の少なくとも 1 つが文字列に見つからない場合、その preg_replace は実行されるべきではありません)

2 番目の問題の例:

言及された文字がどこにも見つからないため、この文にはピリオドは必要ありません

この別の文には、それが必要です! なんで?上記の文字の少なくとも 1 つが含まれているため

(もちろん、終了期間はまだ存在しない場合にのみ配置する必要があります)

ご協力いただきありがとうございます!

4

1 に答える 1

4

これが最初の問題に対する答えです。最後から 3 番目の置換が問題です。

$fixed = preg_replace( '/([!?,.])(\S)/', '$1 $2', $fixed); # spaces after punctuation, if it doesn't exist already

最初のピリオドは文字クラスに一致し、2 番目のピリオドはスペース以外の文字として一致します。次に、スペースを挿入します。一致は重複できないため、3 番目と 4 番目のピリオドに一致し、スペースなどが挿入されます。これはおそらく次のように修正するのが最適です。

$fixed = preg_replace( '/[!?,.](?![!?,.\s])/', '$0 ', $fixed);

2 番目の要件に対処する方法は次のとおりです (最後から 2 番目を置き換えますpreg_replace)。

$fixed = trim($fixed);
$fixed = preg_replace( '/[!?.,].*(?<![.!?])$/', '$0.', $fixed);

まず、先頭と末尾の空白を取り除き、この懸念を末尾のピリオドから分離します。次に、preg_replaceは文字列内の句読点を見つけようとし、見つかった場合は、文字列の末尾まですべてに一致します。置換により、一致が元に戻され、ピリオドが追加されます。否定の後読みに注意してください。文字列が文末の句読点で終わっていないことを表明します。

于 2012-11-18T21:40:43.540 に答える