Regex usage – maybe

I have plain text which is kind of pre-formatted with hyphenated words (and similar).
So I thought it could be an idea to use regex to join the hyphenated words.
But the text is in German (will be same in other languages with special characters as well) and characters like ä, ö, ü won’t work.
Here what I have and which doesn’t work

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property cA : a reference to current application

property theContent : "Eine Übertragung durch kontaminierte Oberflä- chen ist theoretisch vorstellbar, da SARS-CoV-2- Viren unter Laborbedingungen auf Flächen eine gewisse Zeit lang infektiös bleiben können. Im Vergleich zur aerogenen SARS-CoV-2-Übertragung wird die Bedeutung der Verbreitung des Virus durch kontaminierte Flächen aktuell gering einge- schätzt. Die Inkubationszeit beträgt 2 – 14 Tage (im Durchschnitt 5 – 6 Tage). Als Haupteintritts- pforten für SARS-CoV-2 gelten die Schleimhäute des Nasen-Rachen-Raums; eine Aufnahme via Kon- junktiven und Tränennasengang wird diskutiert, konnte allerdings bislang nicht eindeutig belegt werden."

set theString to cA's NSString's stringWithString:theContent
set checkString to theString's mutableCopy()

-----------------------------------------------------------------
set regEx to "\\w-\\s\\w"
set cRegex to cA's NSRegularExpression's regularExpressionWithPattern:(regEx) options:(0) |error|:(missing value)
set zRangeList to (cRegex's matchesInString:(theString) options:(0) range:({0, theString's |length|()}))'s valueForKey:("range")
set vCount to (count of zRangeList)

repeat with i from vCount to 1 by -1 --zRange in zRangeList
	# replace the "- " in the range
end repeat

Any hints how to proceed are appreciated.

Happy Holidays

Hi Andreas.

Do you want to remove the hyphens, or just the spaces after them?

Edit: This seems to suit your text. Where a hyphen’s followed by white space, it removes both the hyphen and the space if they’re followed by a lower-case character or digit, and just the white space if the following character’s upper case:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property cA : a reference to current application

property theContent : "Eine Übertragung durch kontaminierte Oberflä- chen ist theoretisch vorstellbar, da SARS-CoV-2- Viren unter Laborbedingungen auf Flächen eine gewisse Zeit lang infektiös bleiben können. Im Vergleich zur aerogenen SARS-CoV-2-Übertragung wird die Bedeutung der Verbreitung des Virus durch kontaminierte Flächen aktuell gering einge- schätzt. Die Inkubationszeit beträgt 2 – 14 Tage (im Durchschnitt 5 – 6 Tage). Als Haupteintritts- pforten für SARS-CoV-2 gelten die Schleimhäute des Nasen-Rachen-Raums; eine Aufnahme via Kon- junktiven und Tränennasengang wird diskutiert, konnte allerdings bislang nicht eindeutig belegt werden."

set theString to cA's NSString's stringWithString:theContent

-----------------------------------------------------------------
-- Match either a hypen and white space which follow a word character and precede a lower-case one
-- or white space which follows a hyphen and precedes an upper-case character.
set regEx to "(?<=\\w)-\\s++(?=[[:lower:]\\d])|(?<=-)\\s++(?=[[:upper:]])"

set theString to theString's stringByReplacingOccurrencesOfString:(regEx) withString:("") options:(cA's NSRegularExpressionSearch) range:({0, theString's |length|()})

Wow.

Thanks a lot.
I’ll try to understand the whole “expression” tomorrow morning our time.

If we put regular expressions aside for the moment, and stick to a single language, it may be worth looking at what happens (at the margin) if we:

  1. segment the string into a list of space-delimited words,
  2. start with the first word,
  3. and add the rest (sometimes dropping a space or hypen) one by one.
-- atMargin :: String -> String -> String
on atMargin(sofar, nextWord)
	if (character -1) of sofar = "-" then
		
		if isLower(character 1 of nextWord) then
			-- HYPHEN DROPPED
			(text 1 thru -2 of sofar) & nextWord
		else
			-- SPACE DROPPED
			sofar & nextWord
		end if
		
	else
		-- DEFAULT
		sofar & space & nextWord
	end if
end atMargin

A full script below, yielding the same result as Nigel’s Regex.

(Note that the the built in words of is a bit too powerful for our segmentation (it strips off the hyphens that interest us here), but we can use an NSString method, wrapping it as a |words| handler).


Full Script
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions


property theContent : "Eine Übertragung durch kontaminierte Oberflä- chen ist theoretisch vorstellbar, da SARS-CoV-2- Viren unter Laborbedingungen auf Flächen eine gewisse Zeit lang infektiös bleiben können. Im Vergleich zur aerogenen SARS-CoV-2-Übertragung wird die Bedeutung der Verbreitung des Virus durch kontaminierte Flächen aktuell gering einge- schätzt. Die Inkubationszeit beträgt 2 – 14 Tage (im Durchschnitt 5 – 6 Tage). Als Haupteintritts- pforten für SARS-CoV-2 gelten die Schleimhäute des Nasen-Rachen-Raums; eine Aufnahme via Kon- junktiven und Tränennasengang wird diskutiert, konnte allerdings bislang nicht eindeutig belegt werden."


--------------- WHAT HAPPENS AT THE MARGIN ? -------------

-- atMargin :: String -> String -> String
on atMargin(sofar, nextWord)
	if (character -1) of sofar = "-" then
		
		if isLower(character 1 of nextWord) then
			-- HYPHEN DROPPED
			(text 1 thru -2 of sofar) & nextWord
		else
			-- SPACE DROPPED
			sofar & nextWord
		end if
		
	else
		-- DEFAULT
		sofar & space & nextWord
	end if
end atMargin


--------------------------- TEST -------------------------
on run
	set allWords to |words|(theContent)
	
	foldl(atMargin, item 1 of allWords, rest of allWords)
end run


------------------------- GENERIC ------------------------

-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
	tell mReturn(f)
		set v to startValue
		set lng to length of xs
		repeat with i from 1 to lng
			set v to |λ|(v, item i of xs, i, xs)
		end repeat
		return v
	end tell
end foldl


-- isLower :: Char -> Bool
on isLower(c)
	set d to (id of c) - 97 -- id of "a"
	d ≥ 0 and d < 26
end isLower


-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
	-- 2nd class handler function lifted into 1st class script wrapper. 
	if script is class of f then
		f
	else
		script
			property |λ| : f
		end script
	end if
end mReturn


-- words :: String -> [String]
on |words|(s)
	set cA to current application
	(((cA's NSString's stringWithString:(s))'s ¬
		componentsSeparatedByCharactersInSet:(cA's ¬
			NSCharacterSet's whitespaceAndNewlineCharacterSet()))'s ¬
		filteredArrayUsingPredicate:(cA's ¬
			NSPredicate's predicateWithFormat:"0 < length")) as list
end |words|
1 Like