11
votes

Quelqu'un a-t-il une extrait de code PHP pour saisir la première "phrase" dans une chaîne?

Si j'ai une description comme:

"Nous préférons les questions qui peuvent être répondues, pas seulement discutées. Fournir des détails. Écrivez clairement et simplement."

Et tout ce que je veux, c'est:

"Nous préférons les questions qui peuvent être répondues, pas seulement discutées."

Je pense que je rechercherais une expression régulière, comme "[.! \?]", Déterminez les Strows, puis faites une substrité de la chaîne principale, mais j'imagine que c'est une chose commune à faire, espérant que quelqu'un a Un extrait de couché.


1 commentaires

C'est un problème véritablement difficile. Je recommande de rechercher un package NLP si vous avez besoin de résultats robustes. Un tokéniseur peut identifier les caractères de fin de la phrase (soit "?", ".", ";", Etc., en fonction de votre utilisation prévue), et vous pouvez diviser à ce sujet.


7 Réponses :


8
votes
<?php
$text = "We prefer questions that can be answered, not just discussed. Provide details. Write clearly and simply.";
$array = explode('.',$text);
$text = $array[0];
?>

4 commentaires

+1 à cette réponse. Il convient de noter que cela explosera sur tous. (C'est-à-dire le caractère de la période). Donc, si la phrase contient des abréviations telles que "I.e" ou 'E.G.' Vous rencontrerez des problèmes. En dehors de cela, c'est l'option la plus facile.


Cependant, toutes les phrases ne sont pas finies par "." S. J'ai besoin de quelque chose qui traiterait de "!" et "?" Aussi bien je suis sûr que cela devrait utiliser Regexp, je pense.


Vous pouvez également diviser des éléments de $ de $ par '!', '?', Etc., etc.


Mais vous ne pouvez pas choisir de manière dynamique laquelle scinder.



0
votes

Essayez ceci:

reset(explode('.', $s, 2));


0 commentaires

22
votes

Une expression légèrement plus coûteuse, cependant sera plus adaptable si vous souhaitez sélectionner plusieurs types de ponctuation en tant que terminateurs de phrases.

$sentence = preg_replace('/(.*?[?!.](?=\s|$)).*/', '\\1', $string);


13 commentaires

Merci pour cela. Je suppose que je peux accepter le coût, comme il sera mis en cache.


En fait, juste réalisé, il manquait une pièce. Parce que cela attrape tout jusqu'à la fin, il chute le caractère réel de ponctuation. UNE "." À la fin de la recherche, l'expression de la recherche dans les parens semble résoudre. freg_replace ('/([^? !.]*.).*/', '\\ 1', $ str);


Vous devez avoir attrapé le code avant de modifier :) Si vous regardez à nouveau c'est ce que j'ai posté.


Oui, j'ai vu ça juste après avoir posté mon commentaire. Quelqu'un ci-dessous indique que cela devrait être une période (ou un autre terminateur de phrases) suivi d'au moins un espace vide (pour permettre des noms de domaine par exemple). J'ai pris un coup de poignard mais n'a pas pu comprendre la bonne expression pour cela et ajouter "\ s" ne fonctionnait pas.


Cette regex échouera si la chaîne contient un nombre réel tel que 3.14, il le saute alors au premier point décimal.


String de test pour commentaire précédent: Nous préférons les prix inférieurs à 7,50 USD. Toute hausse, nous n'échèterons pas.


Ce n'était pas dans les exigences données, mais peut être facilement modifiée en vérifiant un caractère blancheur \ s


FWIW, il suffit d'ajouter \ s ne travaillait pas pour moi (voir ci-dessus). Merci gars, c'est un extrait serviable.


Oui, j'ai compris ensuite qu'un simple \ s ne suffirait pas, j'ai donc inclus un exemple en utilisant un regard positif pour trouver des espaces.


Beau travail ian. N'a pas vu votre regex amélioré, donc j'ai fourni une alternative ci-dessous. Vos sont plus élégants cependant. Gloire.


D'accord, afin de ne pas battre un cheval mort ici, mais j'ai fini par essayer d'utiliser ce code récemment sur les résultats renvoyés de YouTube's API, et étrangement, lorsque vous utilisez des flux de playlist, cela n'a pas fonctionné comme prévu. J'ai ensuite utilisé la solution de Dyve, et cela a fait .. me demander si les chaînes Unicode sont un facteur.


Cette regex échoue si la période est suivie d'une nouvelle ligne au lieu d'un espace. Vous voudrez peut-être exécuter Preg_replace ('/ \ s + /', '', $ texte); d'abord.


Vous devez utiliser le modificateur S . Par exemple. '/ ^ (. *? [?!..]) (\ S | $). * / s'



0
votes
current(explode(".",$input));

0 commentaires

0
votes

J'utiliserais probablement l'une des multitudes des fonctions de sous-chaînes / scindées à chaîne dans PHP (certains mentionnés ici déjà). Mais aussi chercher "." Ou ". \ N" (et éventuellement ". \ N \ r") au lieu de "". Juste au cas où une raison quelconque, la phrase contient une période qui n'est pas suivie d'un espace. Je pense que cela durcira la probabilité que vous obteniez de véritables résultats.

Exemple, recherchant juste "". sur: p> xxx pré>

vous obtiendra: p> xxx pré>

Quand vraiment, je suis sûr que vous préféreriez: P>

"I like stackoverflow.com."


2 commentaires

La plupart des cordes n'auront probablement pas de nouvelles lignes à l'intérieur d'eux.


Je pense cependant que de nombreuses chaînes (et certains dans mon projet) auront des URL ... il serait donc bon de comprendre la solution pour cela, bien que la réponse acceptée ci-dessus soit bonne pour le moment.



4
votes

Mon précédente regex semblait travailler dans le testeur mais pas en PHP réel. J'ai édité cette réponse pour fournir un code PHP complet et de travail et une regex améliorée.

$string = 'A simple test!';
var_dump(get_first_sentence($string));

$string = 'A simple test without a character to end the sentence';
var_dump(get_first_sentence($string));

$string = '... But what about me?';
var_dump(get_first_sentence($string));

$string = 'We at StackOverflow.com prefer prices below US$ 7.50. Really, we do.';
var_dump(get_first_sentence($string));

$string = 'This will probably break after this pause .... or won\'t it?';
var_dump(get_first_sentence($string));

function get_first_sentence($string) {
    $array = preg_split('/(^.*\w+.*[\.\?!][\s])/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
    // You might want to count() but I chose not to, just add   
    return trim($array[0] . $array[1]);
}


2 commentaires

Cela ne semble pas fonctionner réellement. L'avez-vous changé depuis que vous avez posté pour la première fois?


Donc, cela non seulement travaillé maintenant, mais à la fin, cela a réellement géré mon problème du monde réel, alors que Ian n'a pas ... (cependant, il l'a fait). Comme je l'ai commenté ci-dessus, cela est peut-être dû au fait que les résultats sont des chaînes unicode ... pas sûres, mais la nourriture à la pensée. Merci pour la fonction - je vais définir. Utilisez-le à nouveau et encore.



3
votes

Essayez ceci: xxx

sortie est:

Mon nom est Younas. Je vis au Pakistan.


0 commentaires