This question already has an answer here:
Reference - What does this regex mean?
(1 answer)
Closed 5 years ago.
Why does this happen:
filename
=> "/Users/user/Desktop/work/arthouse/digitization/in-process/cat.jpg"
[4] pry(DigitizedView)> filename.gsub(/.*\//,'')
=> "cat.jpg"
What is the regex in the first argument of gsub? I know the .* is any number of any characters... but what is the backslash? Why does it delete everything except the cat.jpg part?
Also,
"cat.jpg".scan(/(\w+)-(\d+)([a-z]?)/)
=> []
What is that code doing?
let us examine what this first argument for the gsub method, /.*\// means.
the first and last slashes /.../ denotes that we are dealing with a regex here, not string.
There are two parts to this regex. .* and \/.
.* says that grep any characters, including empty character.
\/ says that grep a string with a slash, /.
This regex would catch,
['/', 'Users/', 'user/', 'Desktop/', 'work/', 'arthouse/', 'digitization/', 'in-process/']
All these strings are now replaced with ''.
Except cat.jpg which doesn't have the slash at the end.
Hope that explanation helps.
edit
In the second part, /(\w+)-(\d+)([a-z]?)/
(\w+): grep a group of word characters (includes numbers)
-: grep for a dash
(\d+): grep a group of numeric digits
([a-z]?): grep for nil char or a single char.
cat.jpg doesn't fit into this regex in many ways. No dash, . in the string. etc.
Therefore, scan will return an empty array.
The Regexp /.*\// matches zero or more characters terminated by a forward slash. The String#gsub method replaces all substrings matching the pattern with the replacement value, in this case ''.
So in this case, the pattern matches the following substrings: '/', 'Users/', 'user/', 'Desktop/', 'work/', 'arthouse/', 'digitization/', and 'in-process/'. It replaces each of these with a blank string. It does not match the remaining substring, cat.jpg, because that substring doesn't terminate with a '/'. So 'cat.jpg' is all that remains.
Related
I am not very familiar with regex. I am trying to match routes in ruby. I have a situation where I have some /route/:id that can take the 'id' parameter. I would like to match the route to any string with parameters as long as there is no forward slash. So anything like /route/123 should match but anything like /route/subroute/123 should not since there is a forward slash after 'subroute'. This is my current regex pattern that matches the '/routes/' portion and allows any string to take place of the 'id' parameter: \A\/routes\/\z*. This works, but if a forward slash is present in the 'id' portion of the route, the match still succeeds. What can I do to allow any string as the 'id' as long as a forward slash is not present?
This ended up being the pattern that worked for my case:
^\/route(\/[A-Za-z0-9\-\_]*)?$
Since it is a route, I found it better to allow only valid url characters and I use the parentheses (...)? for cases of routes that do not take parameters at all so '/route', '/route/', and '/route/abc' will all work, but '/route/abc/' will not.
In Ruby, ^ marks the start of any line, not string, so instead of ^, you need \A. Same with $, to match a string end position, you need to use \z.
Also, to match a single path subpart (the string between two slashes here) you can use a negated character class [^\/]+ / [^\/]*. If you plan to restrict the chars in the subpart to alphanumeric, hyphen and underscore, you can replace [^\/] with [\w-].
So, you can also use
/\A\/route(?:\/[\w-]*)?\z/
Details:
\A - start of string
\/route - a literal /route string
(?:\/[\w-]*)? - an optional (due to the last ?) non-capturing group that matches an optional sequence of / and then zero or more alphanumeric, underscore (\w) or hyphen chars
\z - end of string.
See the Rubular demo (here, ^ and $ are used for demo purposes only since the input is a single multiline text).
I need a regular expression able to match everything but a string starting with a specific pattern (specifically index.php and what follows, like index.php?id=2342343).
Regex: match everything but:
a string starting with a specific pattern (e.g. any - empty, too - string not starting with foo):
Lookahead-based solution for NFAs:
^(?!foo).*$
^(?!foo)
Negated character class based solution for regex engines not supporting lookarounds:
^(([^f].{2}|.[^o].|.{2}[^o]).*|.{0,2})$
^([^f].{2}|.[^o].|.{2}[^o])|^.{0,2}$
a string ending with a specific pattern (say, no world. at the end):
Lookbehind-based solution:
(?<!world\.)$
^.*(?<!world\.)$
Lookahead solution:
^(?!.*world\.$).*
^(?!.*world\.$)
POSIX workaround:
^(.*([^w].{5}|.[^o].{4}|.{2}[^r].{3}|.{3}[^l].{2}|.{4}[^d].|.{5}[^.])|.{0,5})$
([^w].{5}|.[^o].{4}|.{2}[^r].{3}|.{3}[^l].{2}|.{4}[^d].|.{5}[^.]$|^.{0,5})$
a string containing specific text (say, not match a string having foo):
Lookaround-based solution:
^(?!.*foo)
^(?!.*foo).*$
POSIX workaround:
Use the online regex generator at www.formauri.es/personal/pgimeno/misc/non-match-regex
a string containing specific character (say, avoid matching a string having a | symbol):
^[^|]*$
a string equal to some string (say, not equal to foo):
Lookaround-based:
^(?!foo$)
^(?!foo$).*$
POSIX:
^(.{0,2}|.{4,}|[^f]..|.[^o].|..[^o])$
a sequence of characters:
PCRE (match any text but cat): /cat(*SKIP)(*FAIL)|[^c]*(?:c(?!at)[^c]*)*/i or /cat(*SKIP)(*FAIL)|(?:(?!cat).)+/is
Other engines allowing lookarounds: (cat)|[^c]*(?:c(?!at)[^c]*)* (or (?s)(cat)|(?:(?!cat).)*, or (cat)|[^c]+(?:c(?!at)[^c]*)*|(?:c(?!at)[^c]*)+[^c]*) and then check with language means: if Group 1 matched, it is not what we need, else, grab the match value if not empty
a certain single character or a set of characters:
Use a negated character class: [^a-z]+ (any char other than a lowercase ASCII letter)
Matching any char(s) but |: [^|]+
Demo note: the newline \n is used inside negated character classes in demos to avoid match overflow to the neighboring line(s). They are not necessary when testing individual strings.
Anchor note: In many languages, use \A to define the unambiguous start of string, and \z (in Python, it is \Z, in JavaScript, $ is OK) to define the very end of the string.
Dot note: In many flavors (but not POSIX, TRE, TCL), . matches any char but a newline char. Make sure you use a corresponding DOTALL modifier (/s in PCRE/Boost/.NET/Python/Java and /m in Ruby) for the . to match any char including a newline.
Backslash note: In languages where you have to declare patterns with C strings allowing escape sequences (like \n for a newline), you need to double the backslashes escaping special characters so that the engine could treat them as literal characters (e.g. in Java, world\. will be declared as "world\\.", or use a character class: "world[.]"). Use raw string literals (Python r'\bworld\b'), C# verbatim string literals #"world\.", or slashy strings/regex literal notations like /world\./.
You could use a negative lookahead from the start, e.g., ^(?!foo).*$ shouldn't match anything starting with foo.
You can put a ^ in the beginning of a character set to match anything but those characters.
[^=]*
will match everything but =
Just match /^index\.php/, and then reject whatever matches it.
In Python:
>>> import re
>>> p='^(?!index\.php\?[0-9]+).*$'
>>> s1='index.php?12345'
>>> re.match(p,s1)
>>> s2='index.html?12345'
>>> re.match(p,s2)
<_sre.SRE_Match object at 0xb7d65fa8>
Came across this thread after a long search. I had this problem for multiple searches and replace of some occurrences. But the pattern I used was matching till the end. Example below
import re
text = "start![image]xxx(xx.png) yyy xx![image]xxx(xxx.png) end"
replaced_text = re.sub(r'!\[image\](.*)\(.*\.png\)', '*', text)
print(replaced_text)
gave
start* end
Basically, the regex was matching from the first ![image] to the last .png, swallowing the middle yyy
Used the method posted above https://stackoverflow.com/a/17761124/429476 by Firish to break the match between the occurrence. Here the space is not matched; as the words are separated by space.
replaced_text = re.sub(r'!\[image\]([^ ]*)\([^ ]*\.png\)', '*', text)
and got what I wanted
start* yyy xx* end
Just came across this pattern, which I really don't understand:
^[%w-.]+$
And could you give me some examples to match this expression?
Valid in Lua, where %w is (almost) the equivalent of \w in other languages
^[%w-.]+$ means match a string that is entirely composed of alphanumeric characters (letters and digits), dashes or dots.
Explanation
The ^ anchor asserts that we are at the beginning of the string
The character class [%w-.] matches one character that is a letter or digit (the meaning of %w), or a dash, or a period. This would be the equivalent of [\w-.] in JavaScript
The + quantifier matches such a character one or more times
The $ anchor asserts that we are at the end of the string
Reference
Lua Patterns
Actually it will match nothing. Because there is an error: w- this is a start of a text range and it is out of order. So it should be %w\- instead.
^[%w\-.]+$
Means:
^ assert position at start of the string
[%w\-.]+ match a single character present in the list below
+ Quantifier: Between one and unlimited times, as many times as possible, giving back as needed [greedy]
%w a single character in the list %w literally (case sensitive)
\- matches the character - literally
. the literal character .
$ assert position at end of the string
Edit
As the OP changed the question and the tags this answer no longer fits as a proper answer. It is POSIX based answer.
As #zx81 comment:
%w is \w in Lua which means any alphanumeric characters plus "_"
I'm trying to pull the username from a post in rails. I thought the best way to do this would be using regex and pull from the # to the next whitespace character which would give me the username.
e.g in the string:
'#stackoverflow is good for help'
I would be able to pull from the # to the next whitespace character giving me the string 'stackoverflow'
My regex skills are a little lacking so any help would be appreciated.
Thanks.
You can use \S to match any non-whitespace character, for example:
(?<=#)\S*
Will match any sequence of zero or more non-whitespace characters which appear immediately after a # character. The (?<=…) creates a lookbehind assertion, so the # will not be included in the match.
Demonstration
Alternatively, you could use:
#(\S*)
This will match a #, followed by zero or more non-whitespace characters, captured in group 1.
Demonstration
How about this:
regex = /#(\S*)/
\S here matches all non-whitespace character.
I can't figure out what does this regex match:
A: "\\/\\/c\\/(\\d*)"
B: "\\/\\/(\\d*)"
I suppose they are matching some kind of number sequence since \d matches any digit but I'd like to know an example of a string that would be a match for this regex.
The pattern syntax is that specified by ICU. Expressions are created with NSRegularExpression in an iOS app and are correct.
The first matches //c/ + 0 or more digits. The second matches // + 0 or more digits. In both the digits are captured.
An example of a match for A) is //c/123
An example of a match for B) is //12345
When I use Cygwin which emulates Bash on Windows, I sometimes run into situations where I have to escape my escape characters which is what I think is making this expression look so weird. For instance, when I use sed to look for a single '\' I sometimes have to write it as '\\\\'. (Funny, StackOverflow proved my point. If you write 4 backslashes in the comment, it only shows two. So if you process it again, they might all disappear depending on your situation).
Considering this, it might be helpful to think of pairs of backslashes as representing only one if you're coming from a similar situation. My guess would be you are. Because of this I would say Erik Duymelinck is probably spot on. This will capture a sequence of digits that may or may not follow a couple slashes and a c:
//c/000
//00000
This regex matches an odd sequence of characters, which, at first glance, almost seem like a regex, since \d is a digit, and followed by an asterisk (\d*) would mean zero-or-more digits. But it's not a digit, because the escape-slash is escaped.
\\/\\/c\\/(\\d*)
So, for instance, this one matches the following text:
\/\/c\/\
\/\/c\/\d
\/\/c\/\dd
\/\/c\/\ddd
\/\/c\/\dddd
\/\/c\/\ddddd
\/\/c\/\dddddd
...
This one is almost the same
\\/\\/(\\d*)
except you just delete the c\/ from the above results:
\/\/\
\/\/\d
\/\/\dd
\/\/\ddd
\/\/\dddd
\/\/\ddddd
\/\/\dddddd
...
In both cases, the final \ and optional d is [capture group][1] one.
My first impression was that these regexes were intended for escaping in Java strings, meaning they would be completely invalid. If the were escaped for Java strings, such as
Pattern p = Pattern.compile("\\/\\/c\\/(\\d*)");
It would be invalid, because after un-escaping, it would result in this invalid regex:
\/\/c\/(\d*)
The single escape-slashes (\) are invalid. But the \d is valid, as it would mean any digit.
But again, I don't think they're invalid, and they're not escaped for a Java string. They're just odd.