Regex that allows for A-z, 0-9, and dashing in the middle, never on the ends? - ruby

I'm working to create a ruby regex that meets the following conditions:
Supported:
A-Z, a-z, 0-9, dashes in the middle but never starting or ending in a dash.
At least 5, no more than 500 characters
So far I have:
[0-9a-z]{5,500}
Any suggestions on how to update to meet the criteria above?
Thanks

[A-Za-z\d][-A-Za-z\d]{3,498}[A-Za-z\d]
If you are willing to treat _ as a letter also, it's even simpler:
\w[-\w]{3,498}\w

This should work:
[0-9A-Za-z][0-9A-Za-z-]{3,498}[0-9A-Za-z]

Here you go:
/^[0-9A-Za-z][0-9A-Za-z\-]{3,498}[0-9A-Za-z]$/
or if you want the beginning and end to be only 0-9,A-Z,a-z (instead of non dash) then:
Explanation:
The first ^ matches beginning of string.
The next [] matches a A-Z,a-z,0-9
The next [] matches 3 to 498 chars of A-Z,a-z,0-9,dash. Note that we match 3 to 498 chars because we match one char in the beginning and one in the end.
The next [^] is again a A-Z,a-z,0-9.
And lastly we match $ for the end of the string.

This assumes that there are either always dashes or never dashes. It also assumes only one dash is allowed between alphanumeric characters. It's the only way I can think off hand to limit characters instead of number of instances of the string.
(([0-9a-zA-Z]{4,499})|([0-9a-zA-Z][\d]?){2,249})[0-9a-zA-Z]
Assuming there's no limit to the number of adjacent dashes allowed, this would work:
[0-9a-zA-Z][0-9a-zA-Z\d]{3,498}[0-9a-zA-Z]

Related

Discard contractions from string

I have a special use case where I want to discard all the contractions from the string and select only words followed by alphabets which do not contain any special character.
For eg:
string = "~ ASAP ASCII Achilles Ada Stackoverflow James I'd I'll I'm I've"
string.scan(/\b[A-z][a-z]+\b/)
#=> ["Achilles", "Ada", "Stackoverflow", "James", "ll", "ve"]
Note: It's not discarding the whole word I'll and I've
Can someone please help how to discard the whole word which contains contractions?
Try this Regex:
(?:(?<=\s)|(?<=^))[a-zA-Z]+(?=\s|$)
Explanation:
(?:(?<=\s)|(?<=^)) - finds the position immediately preceded by either start of the line or by a white-space
[a-zA-Z]+ - matches 1+ occurrences of a letter
(?=\s|$) - The substring matched above must be followed by either a whitespace or end of the line
Click for Demo
Update:
To make sure that not all the letters are in upper case, use the following regex:
(?:(?<=\s)|(?<=^))(?=\S*[a-z])[a-zA-Z]+(?=\s|$)
Click for Demo
The only thing added here is (?=\S*[a-z]) which means that there must be atleast one lowercase letter
I know that there's an accepted answer already, but I'd like to give my own shot:
(?<=\s|^)\w+[a-z]\w*
You can test it here. This regex is shorter and more efficient (157 steps against 315 from the accepted answer).
The explanation is rather simple:
(?<=\s|^)- This is a positive look behind. It means that we want strings preceded by a whitespace character or the start of the string.
\w+[a-z]\w* - This one means that we want strings composed by letters only (word characters) containing least one lowercase letter, thus discarding words which are whole uppercase. Along with the positive look behind, the whole regex ends up discarding words containing special characters.
NOTE: this regex won't take into account one-letter words. If you want to accomplish that, then you should use \w*[a-z]\w* instead, with a little efficiency cost.

Ruby regex specify length of captured group

I need to match a string of variable length(between 5 and 12), composed of uppercase letters and one or more digits between 1 and 8.
How can I specify that I need the whole captured group's length to be between 5 and 12?
I have tried with parenthesis but with no luck.
I have tried this
\s([A-Z]+[1-8]+[A-Z]+){5,12}\s
My idea was to use the quantifier {5,12} to limit the length of the captured group between parenthesis, but clearly it doesn't work like that.
The string needs to be identified inside a normal text just like
"THE STRING I NEED TO DECODE IS SOMETHING LIKE FD1531FHHKWF BUT NOT LIKE g4G58234JJ"
You actually have two conditions to met:
The length of the match is to be specified with curly brackets {5,12}, and before and after there should be not letters/digits. So:
/(?!\b[A-Z]+\b)\b[A-Z1-8]{5,12}\b/
First, we assure that the lookahead for letters only is negative, then we look for the pattern.
Use positive look-ahead on total size of regex
\s(?=^.{5,12}$)([A-Z]+[1-8]+[A-Z]+)\s
Explanation
(?= # look-ahead match start
^.{5,12}$ # 3 to 15 characters from start to end
) # look-ahead match end

Is there a way to replace a range of characters in a string using gsub?

I would like to replace every character except the last 4 with a "#"...like you would see on a credit card statement. I have accomplished this using the Array#each method to iterate through indexes [0..-4] and then another for [-4..-1] and shoveling results from both into a new string. I'm thinking that maybe this could be better done with regex? But I am new to regex, and google hasn't turned up anything I can use in regards to replacing an entire range without losing the length of the string. I have tried
str.gsub(str[0..-5],'#')
(and a few other things) but it replaces the entire range with a single character. How can I accomplish my goal using regex?
Yep, this is possible with regex.
> "12345678".gsub(/.(?=.{4})/, "#")
=> "####5678"
> "12345678901234".gsub(/.(?=.{4})/, "#")
=> "##########1234"
Explanation:
.(?=.{4}) matches a character only if it's followed by atleast four characters. So it matches all the characters except the last four chars because from the last, fourth character is followed by 3 characters not 4. So it fails to match the 4th char from the last. Likewise for 3rd, 2nd, 1st chars (from the last).
OR
> "12345678901234".gsub(/(?!.{1,4}$)./, "#")
=> "##########1234"
DEMO

How to find whole complete number with ruby regex

I'm looking to find the first whole occurance of a number within a string. I'm not looking for the first digit, rather the whole first number. So, for example, the first number in: w134fklj342 is 134, while the first number in 1235alkj9342klja9034 is 1235.
I have attempted to use \d but I'm unsure how to expand that to include multiple digits (without specifying how long the number is).
I think, you're looking for this regex
\d+
"Plus" means "one or more". This regex will match all numbers within a string, so pick first one.
strings = ['w134fklj342', '1235alkj9342klja9034']
strings.each do |s|
puts s[/\d+/]
end
# >> 134
# >> 1235
Demo: http://rubular.com/r/YE8kPE2SyW
The easiest way to understand regexes is to think of eachbit is one character; e.g: \d or [1234567890] or [0-9] will match one digit.
To expand this one character you have 2 basic options: * and +
* will match the character 0 or more times
+ will match it one or more times
Like Sergio said you should use \d+ to match many digits.
Excellent tutorial for regexes in general: http://www.regular-expressions.info/tutorial.html

How can I write a regex in Ruby that will determine if a string meets this criteria?

How can I write a regex in Ruby 1.9.2 that will determine if a string meets this criteria:
Can only include letters, numbers and the - character
Cannot be an empty string, i.e. cannot have a length of 0
Must contain at least one letter
/\A[a-z0-9-]*[a-z][a-z0-9-]*\z/i
It goes like
beginning of string
some (or zero) letters, digits and/or dashes
a letter
some (or zero) letters, digits and/or dashes
end of string
I suppose these two will help you: /\A[a-z0-9\-]{1,}\z/i and /[a-z]{1,}/i. The first one checks on first two rules and the second one checks for the last condition.
No regex:
str.count("a-zA-Z") > 0 && str.count("^a-zA-Z0-9-") == 0
You can take a look at this tutorial for how to use regular expressions in ruby. With regards to what you need, you can use the following:
^[A-Za-z0-9\-]+$
The ^ will instruct the regex engine to start matching from the very beginning of the string.
The [..] will instruct the regex engine to match any one of the characters they contain.
A-Z mean any upper case letter, a-z means any lower case letter and 0-9 means any number.
The \- will instruct the regex engine to match the -. The \ is used infront of it because the - in regex is a special symbol, so it needs to be escaped
The $ will instruct the regex engine to stop matching at the end of the line.
The + instructs the regex engine to match what is contained between the square brackets one or more time.
You can also use the \i flag to make your search case insensitive, so the regex might become something like this:
^[a-z0-9\-]+/i$

Resources