You can't do this with a single regex. (Well... maybe in Perl.)
(edit: Okay, you can do it with variable-length negative lookbehind, which it appears Java can (almost uniquely!) do; see Cyborgx37's answer. Regardless, imo, you shouldn't do this with a single regex. :))
What you can do is split the string into words and deal with each word individually. My Java is pretty terrible so here is some hopefully-sensible Python:
# Precompile some regex
looks_like_product_number = re.compile(r'\A[-0-9]+\Z')
not_wordlike = re.compile(r'[^a-zA-Z0-9]')
not_wordlike_or_hyphen = re.compile(r'[^-a-zA-Z0-9]')
# Split on anything that's not a letter, number, or hyphen -- BUT dots
# must be followed by whitespace
words = re.split(r'(?:[^-.a-zA-Z0-9]|[.]\s)+', string)
stripped_words = []
for word in words:
if '-' in word and not looks_like_product_number.match(word):
stripped_word = not_wordlike.sub('', word)
else:
# Product number; allow dashes
stripped_word = not_wordlike_or_hyphen.sub('', word)
stripped_words.append(stripped_word)
pass_to_lucene(' '.join(stripped_words))
When I run this with 'wal-mart 1-2-3', I get back 'walmart 1-2-3'.
But honestly, the above code reproduces most of what the Lucene tokenizer is already doing. I think you'd be better off just copying StandardTokenizer into your own project and modifying it to do what you want.
You can't do this with a single regex. (Well... maybe in Perl.)
(edit: Okay, you can do it with variable-length negative lookbehind, which it appears Java can (almost uniquely!) do; see Cyborgx37's answer. Regardless, imo, you shouldn't do this with a single regex. :))
What you can do is split the string into words and deal with each word individually. My Java is pretty terrible so here is some hopefully-sensible Python:
# Precompile some regex
looks_like_product_number = re.compile(r'\A[-0-9]+\Z')
not_wordlike = re.compile(r'[^a-zA-Z0-9]')
not_wordlike_or_hyphen = re.compile(r'[^-a-zA-Z0-9]')
# Split on anything that's not a letter, number, or hyphen -- BUT dots
# must be followed by whitespace
words = re.split(r'(?:[^-.a-zA-Z0-9]|[.]\s)+', string)
stripped_words = []
for word in words:
if '-' in word and not looks_like_product_number.match(word):
stripped_word = not_wordlike.sub('', word)
else:
# Product number; allow dashes
stripped_word = not_wordlike_or_hyphen.sub('', word)
stripped_words.append(stripped_word)
pass_to_lucene(' '.join(stripped_words))
When I run this with 'wal-mart 1-2-3', I get back 'walmart 1-2-3'.
But honestly, the above code reproduces most of what the Lucene tokenizer is already doing. I think you'd be better off just copying StandardTokenizer into your own project and modifying it to do what you want.
Have you tried this:
[^a-zA-Z0-9-]
java - Remove every special character except hyphen - Stack Overflow
regex - Remove all characters except - Code Review Stack Exchange
Need Regex Pattern: Can't start w num; No special characters except underscore and hyphen; allows characters/nums - Stack Overflow
Regex to check if string has special characters except dash and comma and split
Use [^\\w-]+ regex
String str = "Stack-Overflow";
String str2 = str.split("[^\\w-]+")[0];
System.out.println(str2);
For: Stack-Overflow Output Stack-Overflow
For: Stack Overflow Output Stack
This is a way to do it in C# using Regular expression
string regex = "[^a-zA-Z0-9-]";
var s3 = Regex.Split(inputString, regex)[0];
You can implement a similar type of code in Java also.
This should make it:
"^[A-Za-z_-][A-Za-z0-9_-]*$"
[A-Za-z_-] means a letter or underscore or hyphen
[A-Za-z0-9_-]* is the same, but allows numbers too
So this will allow letters, underscores, hyphens, and numbers, but no numbers at the start.
Looking at your valid input example Account-Numbers_2010 | NewMoney | test_data | a1B2-c3_d4_5e-6f, you may want to also allow spaces and |. This one allows them:
"^[A-Za-z_ |-][A-Za-z0-9_ |-]*$"
This one correctly matches Account-Numbers_2010 | NewMoney | test_data | a1B2-c3_d4_5e-6f and not 2010_Account_Numbers | New$Money | %test*data | 1aB2.
You need 2 parts to the regex. The first character, and then the rest.
^[a-zA-Z_-][a-zA-Z0-9_-]*$
This says:
Start with any character from
a-zorA-Zor_or-. And then follow that by any alphanumeric character or_or-.
Hi, I thought this would be an eayier task but after some googleing I did not find my answer. I found answers to problems where the string had specific Lenghts, mines do not. www.regex101.com/r/66D5Es/1 I used the answer I got for my previous problem, the purple dotted bars seem to indicate the string finds what it's upposed to but I cannot replace/remove the hyphen preceding it. Only lower case letters are important because IT- must not be included
What's the regex statement to remove all special characters (punctuation, numbers, etc.) besides hyphens in hyphenated words (e.g. Spider-Man)?