Q: Regex find one or more character, including those with period or apostrophe or hypen in between. Without last symbol if it occur only once at end re.findall(r'[A-Za-z]+(?=\'|\.|\-[A-Za-z]+)?', txt) 
re.findall(r'[A-Za-z\.\-]+(?:\'[A-Za-z]+)?',txt)

Input
txt = "which would find I'm U.S. co-op, include ending. without the . , but not ' - . rd- "

expected_output
['which', 'would', 'find', "I'm", "U.S.", 'co-op', 'include', 'ending', 'without', 'the', 'but', 'not', 'rd']

I tried the above and variations, but can't get it to work. How to do it?

A: You may use this regex for matches using findall:
\w+(?:['.-]\w+\.?)?

RegEx Demo
RegEx Details:

*

*\w+: Match 1+ word characters

*(?:['.-]\w+\.?)?: Optional non-capturing group that starts with a ' or . or - followed by 1+ word characters and an optional trailing dot.

Code:
import re
txt = "which would find I'm U.S. co-op, include ending. without the . , but not ' - . rd- "
print (re.findall(r"\b\w+(?:['.-]\w+\.?)?", txt))

['which', 'would', 'find', "I'm", 'U.S.', 'co-op', 'include', 'ending', 'without', 'the', 'but', 'not', 'rd']


A: At risk of overthinking your actual issue, here is my attempt with the following assumptions:

*

*You only want to use alphachars [A-Za-z].

*You don't want to match trailing dots in cases like "let's play co-op.".

*Lastly, my guess is you will also want to capture double hyphened words like "non-English-speaking" and abbreviations with more than just a single dot.

Thus, what I came up with is:
\b[a-z]+(?:(?:(\.)|['-])[a-z]+\1?)*

See an online demo.

*

*\b - A word boundary.

*[a-z]+ - 1+ alphachars.

*(?: - Open 1st non-capture group:

*

*(?: - Open 1nd non-capture group:

*

*(\.)|['-] - A 1st capture group holding a dot or a hyphen or apostrophe.

*)[a-z]+\1? - Close 2nd non-capture group, match 1+ alphachars and optionally match what is captured in the 1st capture group (thus a dot).



*)* - Close 1st non-capture group and match 0+ times.



In Python, it could look like something like:
import re
txt = "which would find I'm U.S. co-op, include ending. without the . , but not ' - . rd- "
lst = [m.group(0) for m in re.finditer(r"\b[a-z]+(?:(?:(\.)|['-])[a-z]+\1?)*", txt, re.I)]
print(lst) # ['which', 'would', 'find', "I'm", 'U.S.', 'co-op', 'include', 'ending', 'without', 'the', 'but', 'not', 'rd']

