Removing last character from a line using regex - regex

I just started learning regex and I'm trying to understand how it possible to do the following:
If I have:
helmut_rankl:20Suzuki12
helmut1195:wasserfall1974
helmut1951:roller11
Get:
helmut_rankl:20Suzuki1
helmut1195:wasserfall197
helmut1951:roller1
I tried using .$ which actually match the last character of a string, but it doesn't match letters and numbers.
How do I get these results from the input?

You could match the whole line, and assert a single char to the right if you want to match at least a single character.
.+(?=.)
Regex demo
If you also want to match empty strings:
.*(?=.)

This will do what you want with regex's match function.
^(.*).$
Broken down:
^ matches the start of the string
( and ) denote a capturing group. The matches which fall within it are returned.
.* matches everything, as much as it can.
The final . matches any single character (i.e. the last character of the line)
$ matches the end of the line/input

Related

Regex expression to ignore first and last character

So I am trying to make a regex match for strings of the form:
"catalog.schema.'tablename'" .
The output I am looking for is just catalog.schema.'tablename' leaving out the quotes at the end position.
Can anyone help me out
I tried to do it with the expression
/(?!^|.$)+[^\s]/ which leaves out the end quotes but matches each character.
So I modified it to /(?!^|.$)+[^\s]+/g . This matches the whole sentence but doesn't ignore the end quote.
Depends on the data arround your string and quotationmarks may be within the string.
Why not just this: "(.*?)"
https://regex101.com/r/oaS8o0/1
To answer the question in the title you might simply use:
^.(.*)?.$
https://regex101.com/r/FxJgtW/1
You can just use
(?<=.).+(?=.)
Or, if you cannot use lookbehind:
(?!^).+(?!$)
See the regex demo #1 and regex demo #2.
Since . matches any char other than line break chars, the patterns just match any strings without their start and end chars.
If you don't want to match the first and the last character, you can just use a capture group instead of lookarounds and use the group 1 value.
The first . matches the first of (any) characters, the (.+) is a capture group that matches 1 or more characters, and the . at the end matches the last character of the string.
.(.+).
Regex demo
Or to get the text between the double quotes at the start and the end of the string using a negated character class and a capture group:
^"([^"]+)"$
Regex demo

Regex - Discard the entire string if any part of the string doesn't match the pattern

I have a comma separated string which I want to validate using a regex. What I have written is gives me a match if there a part wrong later in the string. I want to discard it completely if any part is wrong.
My regex : ^(?:[\w\.]+,{1}(?:STR|INT|REAL){1},{1}(\s*|$))+
Positive Case : Component,STR,YoungGenUse,STR,YoungGenMax,STR,OldGenUse,INT,OldGenMax,INT,PermGenUse,INT,PermGenMax,INT,MajCollCnt,INT,MinCollDur,REAL,MinCollCnt,INT,
Negative Case :
Component,STR,YoungGenUse,STR,YoungGenMax,TEST,OldGenUse,INT,OldGenMax,INT,PermGenUse,INT,PermGenMax,INT,MajCollCnt,INT,MinCollDur,REAL,MinCollCnt,INT,
For the second case, my regex gives a match for the bold portion eventhough, later there is an incorrect part (TEST). How can I modify my regex to discard the entire string?
The pattern that you tried would not match TEST in YoungGenMax,TEST because the alternatives STR|INT|REAL do not match it.
It would show until the last successful match in the repetition which would be Component,STR,YoungGenUse,STR,
You have to add the anchor at the end, outside of the repetition of the group, to indicate that the whole pattern should be followed by asserting the end of the string.
There are no spaces or dots in your string, so you might leave out \s* and use \w+ without the dot in the character class. Note that \s could also possibly match a newline.
^(?:\w+,(?:STR|INT|REAL),)+$
Regex demo
If you want to keep matching optional whitespace chars and the dot:
^(?:[\w.]+,(?:STR|INT|REAL),\s*)+$
Regex demo
Note that by repeating the group with the comma at the end, the string should always end with a comma. You can omit {1} from the pattern as it is superfluous.
your regex must keep matching until end of the string, so you must use $ to indicate end of the line:
^(?:[\w.]+,{1}(?:STR|INT|REAL){1},{1}(\s*|$))+$
Regex Demo

Why there are two matches

I think that there is a match,but there are two.That's strange.I want to know why
Why are you surprised? .* matches any number of characters, including 0.
So you get one match that contains the entire line, and a second match that contains the empty string between the first match and the end of the string.
Regular expressions don't just deal with characters, but also with positions between characters (known as anchors). For example ^ matches the position before the first character, $ matches the position after the last character in a string.
A regex engine "walks through" a string, starting from the position before the first character. It then steps forward one character at a time.
For example, when applying the regex .* to "Hello", the regex engine starts before the H. It then matches Hello - after that .* can't match any more characters, so the regex engine returns "Hello" as the first match. The regex engine is now positioned after the o. If you call it again and ask it to match, it will succeed in returning a match because you're asking it to match any string, even an empty one, from the current position - and that's possible.
Why doesn't the regex engine return an infinite number of empty strings, then? It checks whether the last match was started from the end of the string, and if it was, no further matches will be attempted.
Some languages don't even try a regex match once from the final position in a string (Ruby seems to be one example), but I'd say it's more correct to return two matches.
Since it appears more clarification is necessary: The regex engine steps through the string along the positions visualized by |s below:
"|H|e|l|l|o|"
^ Position before the first character
^ Position after the last character

Regex - No "p" at second position

I am learning Regex and after reading this post, I started doing some exercises and I got stuck on this exercise. Here are the two lists of words that should be matched and not matched
I started with
^(.).*\1$
and get bothered with sporous that get matched although it should not. So I found
^(.)(?!p).*\1$
that did the trick.
The best solution (uses one less character than my solution) given here is
^(.)[^p].*\1$
but I don't really understand this pattern. Actually I think I am confused about seeing the ^ anchor in a group [] and I am confused about seeing the ^ anchor somewhere else than at the beginning of the regex.
Can you help to understand what this regex is doing?
Anything in square brackets is a character class. This context uses its own mini-syntax which simply lists the allowed characters [abc] or a range of allowed characters [a-z] or disallowed characters by adding a caret as the very first character in the character class [^a-z].
Your solution uses a negative look-ahead (?!p) that does not consume characters, and just checks if the next character is not p.
The other solution uses a negated character class [^p] that will consume a character other than p.
So, the final solution depends on what you need to match/capture.
Here is the pattern explanation of ^(.)[^p].*\1$
^ start of the string/line
(.) group first character
[^p] any character except p
.* zero or more characters
\1 first matched group again
$ end of the string/line
The above regex matches any string that starts and ends with the same character and not contains p at second position.
For detail explanation visit at regex101.
Read more about Negated Character Classes.
[^p] simply means that any character will match, which is not p.
I'll explain the regex step by step in the following sentences.
^ start of the string
(.) matches any character as group 1
[^p] matches any character that is not p
.* matches any character that repeats zero or more times
\1 matches the exact matched character(s) from group 1
$ end of the string
A good source for learning regex is regex101.
^ means assert position at start of the line, however, in a character class [ ] it equates to match character other than ...
Example:
^test-[^p]-1234
Result:
test-q-1234 // match
test-p-1234 // no match
test-o-1234 // match
https://regex101.com/r/wN4zF9/1

Perl: Matching string not containing PATTERN

While using Perl regex to chop a string down into usable pieces I had the need to match everything except a certain pattern. I solved it after I found this hint on Perl Monks:
/^(?:(?!PATTERN).)*$/; # Matches strings not containing PATTERN
Although I solved my initial problem, I have little clue about how it actually works. I checked perlre, but it is a bit too formal to grasp.
Regular expression to match a line that doesn't contain a word? helps a lot in understanding, but why is the . in my example and the ?: and how do the outer parentheses work?
Can someone break up the regex and explain in simple words how it works?
Building it up piece by piece (and throughout assuming no newlines in the string or PATTERN):
This matches any string:
/^.*$/
But we don't want . to match a character that starts PATTERN, so replace
.
with
(?!PATTERN).
This uses a negative look-ahead that tests a given pattern without actually consuming any of the string and only succeeds if the pattern does not match at the given point in the string. So it's like saying:
if PATTERN doesn't match at this point,
match the next character
This needs to be done for every character in the string, so * is used to match zero or more times, from the beginning to the end of the string.
To make the * apply to the combination of the negative look-ahead and ., not just the ., it needs to be surrounded by parentheses, and since there's no reason to capture, they should be non-capturing parentheses (?: ):
(?:(?!PATTERN).)*
And putting back the anchors to make sure we test at every position in the string:
/^(?:(?!PATTERN).)*$/
Note that this solution is particularly useful as part of a larger match; e.g. to match any string with foo and later baz but no bar in between:
/foo(?:(?!bar).)*baz/
If there aren't such considerations, you can simply do:
/^(?!.*PATTERN)/
to check that PATTERN does not match anywhere in the string.
About newlines: there are two problems with your regex and newlines. First, . doesn't match newlines, so "foo\nbar" =~ /^(?:(?!baz).)*$/ doesn't match, even though the string does not contain baz. You need to add the /s flag to make . match any character; "foo\nbar" =~ /^(?:(?!baz).)*$/s correctly matches. Second, $ doesn't match just at the end of the string, it also can match before a newline at the end of the string. So "foo\n" =~ /^(?:(?!\s).)*$/s does match, even though the string contains whitespace and you are attempting to only match strings with no whitespace; \z always only matches at the end, so "foo\n" =~ /^(?:(?!\s).)*\z/s correctly fails to match the string that does in fact contain a \s. So the correct general purpose regex is:
/^(?:(?!PATTERN).)*\z/s
jippie, first, here's a tip. If you see a regex that is not immediately obvious to you, you can dump it in a tool that explains every token.
For instance, here is the RegexBuddy output:
"
^ # Assert position at the beginning of a line (at beginning of the string or after a line break character) (line feed)
(?: # Match the regular expression below
(?! # Assert that it is impossible to match the regex below starting at this position (negative lookahead)
PATTERN # Match the character string “PATTERN” literally (case insensitive)
)
. # Match any single character that is NOT a line break character (line feed)
)
* # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
\$ # Assert position at the end of a line (at the end of the string or before a line break character) (line feed)
# Perl 5.18 allows a zero-length match at the position where the previous match ends.
# Perl 5.18 attempts the next match at the same position as the previous match if it was zero-length and may find a non-zero-length match at the same position.
"
Some people also use regex101.
A Human Explanation
Now if I had to explain the regex, I would not be so linear. I would start by saying that it is fully anchored by the ^ and the $, implying that the only possible match is the whole string, not a substring of that string.
Then we come to the meat: a non-capturing group introduced by (?: and repeated any number of times by the *
What does this group do? It contains
a negative lookahead (you may want to read up on lookarounds here) asserting that at this exact position in the string, we cannot match the word PATTERN,
then a dot to match the next character
This means that at each position in the string, we assert that we cannot match PATTERN, then we match the next character.
If PATTERN can be matched anywhere, the negative lookahead fails, and so does the entire regex.