正则表达式 - 根据标点符号/空格将字符串拆分为数组

时间:2017-05-09 17:13:08

标签: php regex

我需要一种方法,根据标点符号或空格的存在将字符串拆分成几个不同的部分。

我的意思是,每个单词都应该被分成它自己的数组元素,而且在单词的开头或结尾的标点符号也应该被放入它自己的数组元素中。数组元素。

E.g: 我需要能够将字符串Hello, Harry Potter. I'm Tom Riddle.转换为

array(
   "Hello",
    ", "
    "Harry",
    "Potter"
    ". ",
    "I'm",
    "Tom",
    "Riddle",
    ". "
)

因此,单词中间的标点符号(例如单词中间的撇号)不应导致分离 **编辑:**为了澄清所需的行为,I'mdidn't等应保留一个字,但hello!"okay,等应与开头或结尾的标点符号。

另外,我希望包含在搜索中的标点符号是:

  • 。 (句号/句号)
  • ? (问号)
  • ! (惊叹号)
  • ,(逗号)
  • ; (分号)
  • :(冒号)
  • ( - )(连字符破折号)
  • ((开始括号)
  • )(结束括号)
  • {(start squigly brace)
  • }(结束右手撑)
  • [(开始方括号)
  • ](结束方括号)
  • ' (单引号)
  • " (双引号)
  • ...(elpises)

我找到的最接近我需要的结果是:

preg_split('/(\s|[\.,\/])/', $string, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

然而,问题是:

  • 标点符号中间词计为正常标点符号
  • 包含数组元素的数组元素也不包含空格。 编辑:抱歉模糊不清;通过这个,我的意思是我希望标点字符包含在puntuation标记之后/之前的空格。例如如果是逗号,则为,(后跟空格),但如果是开括号,则为((之前的空格)。
  • 当我添加剩余的标点符号时,我需要(preg_split("/(\s|[\.?!,;:-(){}[]'\"…\/])/",)我收到错误。我非常确定这个错误是由于未转义的字符引起的,所以我通过preg_quote运行了整个事件,返回\.\?\!,;\:\-\(\)\{\}\[\]'"…,但这仍然会出错:Parse error: syntax error, unexpected '…' (T_STRING), expecting ',' or ')' in [...][...] on line 5

我对正则表达式的理解相当有限,但在查看php文档后,我可以收集到上面的代码在它遇到的每个空格中分隔单词,或者每次遇到逗号或标点符号时。 (如果我错在那里,请纠正我?)正如我所理解的那样,在方括号内添加其余字符会使字符串与任何字符分开(?)因为这不是'工作,我想我对这是如何工作有一些基本的误解,所以非常感谢你的解释。

3 个答案:

答案 0 :(得分:4)

这样做会有所不同,但是当您将'作为要拆分的字符时,输出略有不同,因此I'm将被拆分:

$result = preg_split('/(\.\.\.\s?|[-.?!,;:(){}\[\]\'"]\s?)|\s/',
                     $string, null, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

可能会简化,但我只是将省略号...包含在可选空格中,或者将所有其他字符包含在可选空格或空格中。

您需要转义字符类.之外的点[],转义字符类中的[]以及-需要被逃脱或者是先到先后,以免表示范围。显然,您需要转义用于包含模式的引用,在本例中为单'

您没有指定标点符号两侧是否需要空格,并且不清楚此“标点符号中间词是否为正常标点符号”表示它应该或不应该' t count。

答案 1 :(得分:1)

你真的希望所有单词内部标点符号保持附加吗?此外,您似乎想要单独标记每个标点字符(但附加附近的空格),这是大部分工作。如果你真的这样做,这应该做到。附带一个测试字符串,以显示它的工作情况。

$string = "Hello, it's me-me-it's-me!!! o... (a friend?)";
print_r( preg_split("/(\w\S+\w)|(\w+)|(\s*\.{3}\s*)|(\s*[^\w\s]\s*)|\s+/", $string, 
        -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE) );

输出:

Array
(
    [0] => Hello
    [1] => ,
    [2] => it's
    [3] => me-me-it's-me
    [4] => !
    [5] => !
    [6] => !
    [7] => o
    [8] => ... 
    [9] => (
    [10] => a
    [11] => friend
    [12] => ?
    [13] => )
)

这是它的工作原理:

  1. (\w\S+\w)捕获3个以上字符的单词,允许嵌入非字母。
  2. (\w+)捕捉任何单词(以捕捉简短的单词)。
  3. (\s*\.{3}\s*)捕获省略号...以及任何周围空间。
  4. (\s*[^\w\s]\s*)分别捕获任何非字母,非空格字符;但附上任何附近的空间。
  5. \s+任何其他空格(即单词之间)拆分字符串,但捕获。
  6. 如果您想要选择单词中的内容,请将第一个备选项中的\S+替换为您要允许的列表,例如,[\w'-]+以允许撇号和连字符仅

答案 2 :(得分:0)

通常你可以使用模式

word character+[all your punctuation characters here]+word character(*SKIP)(*FAIL)

例如:

\w[\[\].?\"\']\w(*SKIP)(*FAIL)|[\[\].?\"\']

请参阅a demo on regex101.com