0

我需要通过空格、标点符号、换行符将文本分成数组。这是示例文本:

男士夹克是绿色的。他——现代史上最大的明星——骑自行车的速度非常快(每小时 230 公里)。这怎么可能?!他用的是什么自行车?他的自行车的半自动齿轮非常昂贵,对达到这个速度有很大帮助。一些(或者可能很多)声称他是世界上最快的!“我看见他骑自行车了!” John Deer 先生发言。“他设定的速度是每小时133.78公里”,听起来不可思议;听起来很骗人。

我已经有了这样做的正则表达式

preg_split('/(?<=\s)|(?<=\w)(?=[.,:;!?()-])|(?<=[.,!()?\x{201C}])(?=[^ ])/u', $text);

但是目前它将以下内容拆分semi-automatic为两个词,而必须保持为一个词。如果破折号旁边有空格,如semi - automatic,那么这应该是三个单词。我不太明白这个正则表达式是如何工作的,所以感谢任何帮助。

第二个问题是如果文本包含换行符,它会捕获换行符但也会创建冗余元素。请参阅示例- 元素 [8] 和 [9]。元素 [8] 是多余的。我该如何解决它?

4

2 回答 2

1

我没有测试以下内容。

首先让我们更改正则表达式:

/[.,:;!?()\s]|(?<=\s)-(?=\s)/u

解释:

[.,:;!?()\s]- 标点符号分开

|(?<=\s)-(?=\s)- (替代)分割在-其两侧都有一个空格-

接下来,array_filter()对结果执行一次操作,删除空|假元素

编辑:

要保留标点符号,请使用:

/(?=[.,:;!?()\s])|(?<=\s)-(?=\s)/u

我只是用前瞻包围了角色类

编辑2:

/\s|(?=[.,:;!?)])|(?<=\s[("])|(?<=\s)-(?=\s)/u

编辑 3:

\s|(?<=\s)-(?=\s)|(?<=\w)(?=[.,:;!?])|(?<=[.,"!()?\x{201C}])(?=[^ ])

编辑4:

\s|(?<=\s)-(?=\s)|(?<=\w)(?=[.,:;!?)])|(?<=[.,"!()?\x{201C}])(?=[^ ])

解释:

哦,我的,我的头今天不在比赛中。您的正则表达式几乎就在那里,只需要一两个 mod,所以这是最终的正则表达式。

/\s|(?<=\w)(?=[.,:;!?)])|(?<=[.,"!()?\x{201C}])/u

注意:环视只是匹配某些东西,它们消耗零个字符,因此您可能会遇到“零宽度断言”术语。如果我们不使用环视,正则表达式引擎将匹配该字符并将其从匹配中删除。管道元字符|是一个OR,在正则表达式中是一个alternate模式。

\s- 匹配一个空白字符。我们不需要在环顾中使用它,因为无论如何我们都想删除它。

(?<=\w)(?=[.,:;!?)])-OR 匹配一个单词字符的正向lookbehind,\w后跟任何以下标点字符的正向lookahead .,:;!?)

(?<=[.,"!()?\x{201C}])- 或匹配以下标点字符的正向后视.,"!()?\x{201C}。是\x{201C}左双引号(unicode 双字节字符)。

u- 允许 utf-8 字符的修饰符,例如\x{201C}

在你原来的正则表达式中(?=[^ ]),最后是多余的,所以我删除了它。它可以写成(?!\s)相同的,对单个空白字符的负前瞻。

所以你会preg_split()像这样使用:

$return = preg_split('/\s|(?<=\w)(?=[.,:;!?)])|(?<=[.,"!()?\x{201C}])/u', $text, -1, PREG_SPLIT_NO_EMPTY)
于 2013-11-12T13:07:41.967 回答
0

你可以试试这个:

preg_split('/[^\PP.-]|(?<=\s)-(?=\s)|\s+|\.(?!\d)/u', $str, null, PREG_SPLIT_NO_EMPTY);
于 2013-11-12T14:42:36.537 回答