What is the REGEX to split a sentence but excluding some specific cases

Viewed 70

I have a text that I need to split in subsentences but if the text contains special cases such as domain.com or st. moris it gets splitted at those points too.

Here is what I got:

val pattern = "(?<=[.](?<![s][t][.]))"
val text = "here is an axample with cases like st. moris and google.com here. second sentence."
val list = text.split(pattern)
list.foreach(println)

I want this code to return

List(
    "here is an axample with cases like st. moris and google.com here.",
    "second sentence."
)

but instead it returns:

List(
    "here is an axample with cases like st.",
    " moris and google.",
    "com here.",
    "second sentence."
)

How can I make it work?

3 Answers

If you want to split with 1+ whitespaces preceded with a dot that is not itself is preceded with st as a whole word, you may use

val pattern = """(?i)(?<=(?<!\bst)\.)\s+"""

Or, if the number of whitespace chars after the dot can be 0, you may implement the logic to avoid matching a . if it is followed with com, org, etc. as whole words:

val pattern = """(?i)(?<=\.(?<!\bst\.)(?!(?:com|org)\b))\s*+(?!$)"""

See the regex #1 demo and regex #2 demo. Details:

  • (?i) - makes the pattern case insensitive
  • (?<=(?<!\bst)\.) - a location immediately preceded with a dot that is not immediately preceded with a whole word st
  • \s+ - 1 or more whitespaces

Or

  • (?i) - makes the pattern case insensitive
  • (?<=\.(?<!\bst\.)(?!(?:com|org)\b)) - a location immediately preceded with a dot that is not immediately preceded with a whole word st and not immediately followed with com or org as whole words (add more alternatives if needed after |)
  • \s*+ - 0 or more whitespaces matched possessively
  • (?!$) - not at the end of string.

See Scala demo #1 (Scala demo #2):

val pattern = """(?i)(?<=(?<!\bst)\.)\s+"""
// val pattern = """(?i)(?<=\.(?<!\bst\.)(?!(?:com|org)\b))\s*+(?!$)""" // Pattern #2
val text = "here is an axample with cases like st. moris and google.com here. second sentence."
val list = text.split(pattern)
list.foreach(println)

Output:

here is an axample with cases like st. moris and google.com here.
second sentence.

Your code is returning such value because as you have mentioned in pattern you need to split when your mentioned symbol comes. And one of the symbols among you mentioned is "." . So after st when "." Comes it splits. So you have two options either remove "." after st and Google or give something another symbol from pattern before "second" word and remove "." from pattern.

So this one works for me, and can be expanded with different exclusions in the text

((.+(st\.|mr\.|mrs\.))*.+?\.( |$))

Maybe there will be some sub-matches in the group, but you should look only for full matches. Here is the regex101.com example

enter image description here

As you see on the right, only two matches.

To add more exclusions, you should add to the (st\.|mr\.|mrs\.) part string pattern which you would like to count as exclusions.

The domain names are exluded with this part: \.( |$). It says, that the end of the sentence should be a dot and a space(or)end of the line.

Reply if it works in your environment.

Related