I know this sounds like a repeated question, but I'm relatively new to Regex and don't really understand some of the other answers. I managed to get this to work previously with something like
Find: \n+[(a-z)]
Replace: *space*\1
I can't remember the exact terms I used though, and now if I try it the subsequent alphabet is deleted, and online regex testers say the \1 in replace is an invalid expression.
E.g.
I
want
this
To remove
Newlines
should become
I want this
To remove
Newlines
but is instead becoming
I ant his
To remove
Newlines
I don't remember what I used the first time round, but i disabled the "whole word" option in sublime, and somehow managed to remove the newlines without cutting characters. Why is \1 invalid? also what is the difference whether I use "+" or not? I don't really understand what greedy means. Sorry, and thank you!
Edit: thanks for all the responses! I definitely have a lot more to learn about using regex more flexibly, but in this case it was the difference between [(a-z)] and ([a-z]) that I missed.
Your regex does not contain a capturing group. A \1 in the replacement pattern is a backreference to the capture group inside the regex pattern. If the group does not exist, the error pops up.
You seem to want to replace 1+ line breaks before a lowercase letter. Make sure your settings are like this:
The regex is: \h*\R+([a-z]) (where \h* matches 0+ horizontal whitespaces, \R+ matches any 1+ line breaks, CRLF/LF/CR and ([a-z]) matches a lowercase ASCII letter)
Replacement: \1 (where \1 puts back Group 1 value)
Settings:
Note that the case sensitivity must be enabled, too.
You could do it like
(?: )?[\n\r]([a-z])
And replace the occurence with $1 (space, followed by $1), see a demo on regex101.com.
Explanation:
(?: )? # Looks for a space, this is optional
[\n\r] # newline
([a-z]) # a character between a and z, lowercase
Related
Is there a way to use a single regular-expression to match only within another math. For example, if I want to remove spaces from a string, but only within parentheses:
source : "foobar baz blah (some sample text in here) and some more"
desired: "foobar baz blah (somesampletextinhere) and some more"
In other words, is it possible to restrict matching to a specific part of the string?
In PCRE a combination of \G and \K can be used:
(?:\G(?!^)|\()[^)\s]*\K\s+
\G continues where the previous match ended
\K resets beginning of the reported match
[^)\s] matches any character not in the set
See demo at regex101
The idea is to chain matches to an opening parentheses. The chain-links are either [^)\s]* or \s+. To only get spaces \K is used to reset before. This solution does not require a closing ).
In other regex flavors that support \G but not \K, capturing groups can help out. Eg Search for
(\G(?!^)|\()([^)\s]*)\s+
and replace with captures of the 2 groups (depending on lang: $1$2 or \1\2) - Regex101 demo
Further there is (*SKIP)(*F), a PCRE feature for skipping over certain parts. It is often used together with The Trick. The idea is simple: skip this(*SKIP)(*F)|match that - Regex101 demo. Also this can be worked around with capture groups. Eg replace ([^)(]*\(|\)[^)(]*)|\s with$1
One idea is to replace any space between parentheses using a lookahead pattern:
(?=([^\s\(]+ )*\S*\))(?!\S*\s*\()`
The lookahead will attempt to match the last space before the closed parenthesis (\S*\)) and any optional space before ([^\s\(]+ )* (if found).
Detailed Regex Explanation:
: space
(?=([^\s\(]+ )*\S*\)): lookahead non-capturing group
([^\s\(]+ )*: any combination characters not including the open parenthesis and the space characters + space (this group is optional)
\S*\): any non-space character + closed parenthesis
(?!\S*\s*\(): what lookahead should not be
\S*: any non space character (optional), followed by
\s*: any space character (optional), followed by
\(: the open parenthesis
Check the demo here.
I have this regex:
\[tag\](.*?)\[\/tag\]
It match any character between two tags. The problem that is matching also empty contents or just white spaces inside the tags, for example:
[tag][/tag]
[tag] [/tag]
How can I avoid it? Make it to match at least 1 character and not only white spaces. Thanks!
Use
\[tag\](?!\s*\[\/tag\])(.*?)\[\/tag\]
^^^^^^^^^^^^^^^^
See the regex demo and the Regulex graph:
The (?!\s*\[\/tag\]) is a negative lookahead that fails the match if, immediately to the right of the current location, there is 0+ whitespaces, [/tag].
You might change your expression to something similar to this:
\[tag\]([\s\S]+)\[\/tag\]
and you might add a quantifier to it, and bound it with number of chars, similar to this expression:
\[tag\]([\s\S]{3,})\[\/tag\]
Or you could do the same with your original expression as this expression:
Try this regex:
\[(tag)\](?!\s*\[\/\1\])(.*?)\[\/\1\]
This regex matches tag only if it has at least one non-whitespace char.
If this is a PCRE (or php) or NP++ or Perl, use this
(?s)(?:\[tag\]\s*\[/tag\](*SKIP)(?!)|\[tag\]\s*(.+?)\s*\[/tag\])
https://regex101.com/r/aCsOoQ/1
If not, you're stuck with using Stribnetz regex, which works because of
an odd condition of your requirements.
Readable
(?s)
(?:
\[tag\]
\s*
\[/tag\]
(*SKIP)
(?!)
|
\[tag\]
\s*
( .+? ) # (1)
\s*
\[/tag\]
)
There are a thousand regular expression questions on SO, so I apologize if this is already covered. I did look first.
I have string:
Name Subname 11X22 88X620 AB33(20) YA5619 77,66
I need to capture this string: YA5619
What I am doing is just finding AB33(20) and after this I am capturing until first white space. But AB33(20) can be AB-33(20) or AB33(-20) or AB33(-1).
My preg_match regex is: (?<=\bAB\d{2}\(\d{2}\)\s).+?(?=\s)
Why I am getting error when I change from \d{2} to \d+?
For final result I was thinking this regix will work but no:
(?<=\bAB-?\d+\(-?\d+\)\s).+?(?=\s)
Any ideas what I am doing wrong?
With most regex flavors, lookbehind needs to evaluate to a fixed-length sequence, so you can't use variable quantifiers like * or + or even {1,2}.
Instead of using lookaround, you can simply match your marker pattern and then forget it with \K.
AB-?\d+(?:\(-?\d+\))? \K[^ ]+
demo: https://regex101.com/r/8XXngH/1
It depends on the language. If it is in .NET for example, it matches due to the various length in the lookbehind.
Another solution might be to use a character class and add the character you would allow to match. Then match a whitespace character and capture in a group matching \S+ which matches 1+ times not a whitespace character.
\bAB[()\d-]+\s\K\S+
Explanation
\bAB Match literally prepended with word boundary to prevent AB being part of a larger match.
[()\d-]+ Match 1+ times any of the listed character in the character class
\s Match a whitespace char (or \s+ to match 1 or more)
\K Reset the starting point of the reported match( Forget what was matched)
\S+ Match in a group 1+ times not a whitespace character
Regex demo | Php demo
In $string, I'm trying to phase out the first "-1" so the output of the string will be "test test test-Long.xml".
$string = 'test test test-1-Long.xml'
$string -replace '^(.*)-?\d?(-?.*)\.xml$', '$1$2'
My issue is that I need to make that same first "-1" pattern optional, as both the hyphen and number could not be there as well.
Why is the "?" operator not working? I've also tried {0,1} after each as well with no luck.
Regexes are greedy, so the engine can't decide what to match, and it is ambiguous.
I am not sure it's the best solution, but I could make it work this way:
$string -replace '^([^\-]*)-?\d?(-?.*)\.xml$', '$1$2'
Sole change: the first group must not contain the dash: that kind of "balances" the regex, avoiding the greedyness and that yields:
test test test-Long
Note: the output is not test test test-Long.xml as required in your answer. To do that, simply remove the xml suffix:
$string -replace '^([^\-]*)-?\d?(-?.*)', '$1$2'
The $string -replace '^(.*?)(?:-\d+)?(-.*?)\.xml$', '$1$2' should work if the hyphen is obligatory in the input. Or $string -replace '^((?:(?!-\d+).)*)(?:-\d+)?(.*)\.xml$', '$1$2' in case the input may have no hyphen.
See the regex demo 1 and regex demo 2.
Pattern details:
^ - start of string
(.*?) - Group 1 capturing any 0+ characters other than a newline as few as possible (as the *? quantifier is lazy) up to the first (NOTE: to increase regex performance, you may use a tempered greedy token based pattern instead of (.*?) - ((?:(?!-\d+).)*) that matches any text, but -+1 or more digits, thus, acting similarly to negated character class, but for a sequence of symbols)
(?:-\d+)? - non-capturing group with a greedy ? quantifier (so, this group has more priority for the regex engine, the previous capture will end before this pattern) capturing a hyphen followed with one or more digits
(-.*?) - Group 3 capturing an obligatory - and any 0+ chars other than LF, as few as possible up to
\.xml - literal text .xml
$ - end of string.
Why is the "?" operator not working?
It is not true. The quantifier ? works well as it matches one or zero occurrences of the quantified subpattern. However, the issue arises in combination with the first .* greedy dot matching subpattern. See your regex in action: the first capture group grabs the whole substring up to the last .xml, and the second group is empty. Why?
Because of backtracking and how greedy quantifier works. The .* matches any characters, but a newline, as many as possible. Thus, it grabs the whole string up to the end. Then, backtracking starts: one character at a time is given back and tested against the subsequent subpatterns.
What are they? -?\d?(-?.*) - all of them can match an empty string. The -? matches an empty string before .xml, ok, \d? matches there as well, -? and .* also matches there.
However, the .* grabs the whole string again, but there is the \.xml pattern to accommodate. So, the second capture group is just empty. In fact, there are more steps the regex engine performs (see the regex debugger page), but the main idea is like that.
Trying to create a pattern that matches an opening bracket and gets everything between it and the next space it encounters.
I thought \[.*\s would achieve that, but it gets everything from the first opening bracket on. How can I tell it to break at the next space?
\[[^\s]*\s
The .* is a greedy, and will eat everything, including spaces, until the last whitespace character. If you replace it with \S* or [^\s]*, it will match only a chunk of zero or more characters other than whitespace.
Masking the opening bracket might be needed. If you negate the \s with ^\s, the expression should eat everything except spaces, and then a space, which means up to the first space.
You could use a reluctant qualifier:
[.*?\s
Or instead match on all non-space characters:
[\S*\s
Use this:
\[[^ ]*
This matches the opening bracket (\[) and then everything except space ([^ ]) zero or more times (*).
I suggest using \[\S*(?=\s).
\[: Match a [ character.
\S*: Match 0 or more non-space characters.
(?=\s): Match a space character, but don't include it in the pattern. This feature is called a zero-width positive look-ahead assertion and makes sure you pattern only matches if it is followed by a space, so it won't match at the end of line.
You might get away with \[\S*\s if you don't care about groups and want to include the final space, but you would have to clarify exactly which patterns need matching and which should not.
You want to replace . with [^\s], this would match "not space" instead of "anything" that . implies