Regex - Extract a substring from a given string - regex

I have a string here, This is a string: AAA123456789.
So the idea here is to extract the string AAA123456789 using regex.
I am incorporating this with X-Path.
Note: If there is a post to this, kindly lead me to it.
I think, by right, I should substring(myNode, [^AAA\d+{9}]),
I am not really sure bout the regex part.
The idea is to extract the string when met with "AAA" and only numbers but 9 consequent numbers only.

Pure XPath solution:
substring-after('This is a string: AAA123456789', ': ')
produces:
AAA123456789
XPath 2.0 solutions:
tokenize('This is a string: AAA123456789 but not an double',
' '
)[starts-with(., 'AAA')]
or:
tokenize('This is a string: AAA123456789 but not an double',
' '
)[matches(., 'AAA\d+')]
or:
replace('This is a string: AAA123456789 but not an double',
'^.*(A+\d+).*$',
'$1'
)

Alright, after referencing answers and comments by wonderful people here, I summarized my findings with this solution which I opted for. Here goes,
concat("AAA", substring(substring-after(., "AAA"), 1, 9)).
So I firstly, substring-after the string with "AAA" as the 1st argument, with the length of 1 to 9...anything more, is ignored. Then since I used the AAA as a reference, this will not appear, thus, concatenating AAA to the front of the value. So this means that I will get the 1st 9 digits after AAA and then concat AAA in front since its a static data.
This will allow the data to be correct no matter what other contributions there is.
But I like the regex by #Dimitre. The replace part. The tokenize not so as what if there isn't space as the argument. The replace with regex, this is also wonderful. Thanks.
And also thanks to you guys out there to...

First, I'm pretty sure you don't mean to have the [^ ... ]. That defines a "negative character class", i.e. your current regex says, "Give me a single character that is not one of the following: A0123456789{}". You probably meant, plainly, "AAA(\d{9})". Now, according to this handy website, XPath does support capture groups, as well as backreferences, so take your pick:
"AAA(\d{9})"
And extracting $1, the first capture group, or:
"(?<=AAA)\d{9}"
And taking the whole match ($0).

Can you try this :
A{3}(\d{9})

Related

Substitute every character after a certain position with a regex

I'm trying to use a regex replace each character after a given position (say, 3) with a placeholder character, for an arbitrary-length string (the output length should be the same as that of the input). I think a lookahead (lookbehind?) can do it, but I can't get it to work.
What I have right now is:
regex: /.(?=.{0,2}$)/
input string: 'hello there'
replace string: '_'
current output: 'hello th___' (last 3 substituted)
The output I'm looking for would be 'hel________' (everything but the first 3 substituted).
I'm doing this in Typescript, to replace some old javascript that is using ugly split/concatenate logic. However, I know how to make the regex calls, so the answer should be pretty language agnostic.
If you know the string is longer than given position n, the start-part can be optionally captured
(^.{3})?.
and replaced with e.g. $1_ (capture of first group and _). Won't work if string length is <= n.
See this demo at regex101
Another option is to use a lookehind as far as supported to check if preceded by n characters.
(?<=.{3}).
See other demo at regex101 (replace just with underscore) - String length does not matter here.
To mention in PHP/PCRE the start-part could simply be skipped like this: ^.{1,3}(*SKIP)(*F)|.

End a regular expression pattern with a string

all. I have spent some time now to learn regular expression, but eventually there is a problem I cannot solve properly.
Lets assume the following 'string' (html-extract):
"{'2018-05-02', '2018-01-05', r, '2018-07-01', '2017-07-02', '2016-07-31' random_text XYCCC Letters and 55565798 ]}"
My intention is, to extract all values from '2018-05-02' ... to (and excluding) random_text. I tried to achieve this through chosing the "anything but" structure to achieve this [^a] (not a):
\'[^random]*
The above does not do the job, because random is not a string, but a set of characters, hence the 'r' in the string will split my extracted value.
If there is no r in the text before the word random_text, this would work fine:
\'[^r]*
Is there any way to include a specific string as the end of my sequence. e.g.
start: \'
repeated characters unlike string: [^{my_string}]*
Appreciate any insight :)
This regex will do the job:
'.+'(?= random)
Just replace random with the string you want to exclude at the end.
Demo & explanation

how to use regex to split a format string?

I want to use regex to split some string like this #key='value' to key and value.
my regex is [^#'=]+[^'=], the output is good when the length of key and value is > 1, but sometimes when the length is only 1 char, the output is not correct.
Can anybody suggest improvements for my regex?
If you'd like to capture the key and value, you might try this:
/^#([^=]+)='([^']+)'$/
Then you will have the key in $1 and the value in $2.
EDIT:
I think I see what you're doing. Change your regex simply to [^#'=]+ to see the difference. However we can't tell help you unless you tell us what language you're using and some sample code.
^#[A-Za-z0-9]+\s*=\s*'[A-Za-z0-9\s]+'
This captures
#Key = 'value'
#key='value'
#k = 'value'
etc..
\A#([^=]+)='([^']+)'
will work as the regex but it doesn't take into account escaping of the apostrophe. this is 2 capture groups... \A says start of string... then # then group.... (not= one or more) =' Group( not ' ) followed by '

What regular expression can I use to split a string into a a-zA-Z pairs?

Can somebody tell me how a regular expression should look like which searches in
V. Guimaraes - FC-Porto
and gives out:
V. Guimaraes
FC-Porto
The Source also could be:
V. Guimaraes - FC-Porto 2:2
V. Guimaraes - FC-Porto Foo
So, I don't want my pair to contain the score.
You could just split the string at " - " with your programing language's basic string functions. This way you don't even need any regular expressions.
how about (.*) - (.*)?
([\S\W]*)[\s]{1}-[\s]{1}([\S\W]*)
And you can fetch answer from group 1 and group 2 $1:$2
Search for: "(V.\s+Guimaraes)\s*-\s*(FC-Porto\b).*?"\s+"\1\s*-\s*\2.*?"
Replace with: "$1"\r"$2"
So, if your are using PHP, it will be:
$result = preg_replace('/"(V.\s+Guimaraes)\s*-\s*(FC-Porto\b).*?"\s+"\1\s*-\s*\2.*?"/', '"$1"\r"$2"', $sourcestring);
The key is $1 $2 which hold the first and the second result.
\r means return characters (enter), you can replace it with anything you wish, e.g. a space.
Next time, please mention regex library or application you are using.
Use the split function of your preferred language to do this. eg Python
>>> s="V. Guimaraes - FC-Porto 2:2"
>>> s.split("-",1)
['V. Guimaraes ', ' FC-Porto 2:2']

regex to match a maximum of 4 spaces

I have a regular expression to match a persons name.
So far I have ^([a-zA-Z\'\s]+)$ but id like to add a check to allow for a maximum of 4 spaces. How do I amend it to do this?
Edit: what i meant was 4 spaces anywhere in the string
Don't attempt to regex validate a name. People are allowed to call themselves what ever they like. This can include ANY character. Just because you live somewhere that only uses English doesn't mean that all the people who use your system will have English names. We have even had to make the name field in our system Unicode. It is the only Unicode type in the database.
If you care, we actually split the name at " " and store each name part as a separate record, but we have some very specific requirements that mean this is a good idea.
PS. My step mum has 5 spaces in her name.
^ # Start of string
(?!\S*(?:\s\S*){5}) # Negative look-ahead for five spaces.
([a-zA-Z\'\s]+)$ # Original regex
Or in one line:
^(?!(?:\S*\s){5})([a-zA-Z\'\s]+)$
If there are five or more spaces in the string, five will be matched by the negative lookahead, and the whole match will fail. If there are four or less, the original regex will be matched.
Screw the regex.
Using a regex here seems to be creating a problem for a solution instead of just solving a problem.
This task should be 'easy' for even a novice programmer, and the novel idea of regex has polluted our minds!.
1: Get Input
2: Trim White Space
3: If this makes sence, trim out any 'bad' characters.
4: Use the "split" utility provided by your language to break it into words
5: Return the first 5 Words.
ROCKET SCIENCE.
replies
what do you mean screw the regex? your obviously a VB programmer.
Regex is the most efficient way to work with strings. Learn them.
No. Php, toyed a bit with ruby, now going manically into perl.
There are some thing ( like this case ) where the regex based alternative is computationally and logically exponentially overly complex for the task.
I've parse entire php source files with regex, I'm not exactly a novice in their use.
But there are many cases, such as this, where you're employing a logging company to prune your rose bush.
I could do all steps 2 to 5 with regex of course, but they would be simple and atomic regex, with no weird backtracking syntax or potential for recursive searching.
The steps 1 to 5 I list above have a known scope, known range of input, and there's no ambiguity to how it functions. As to your regex, the fact you have to get contributions of others to write something so simple is proving the point.
I see somebody marked my post as offensive, I am somewhat unhappy I can't mark this fact as offensive to me. ;)
Proof Of Pudding:
sub getNames{
my #args = #_;
my $text = shift #args;
my $num = shift #args;
# Trim Whitespace from Head/End
$text =~ s/^\s*//;
$text =~ s/\s*$//;
# Trim Bad Characters (??)
$text =~ s/[^a-zA-Z\'\s]//g;
# Tokenise By Space
my #words = split( /\s+/, $text );
#return 0..n
return #words[ 0 .. $num - 1 ];
} ## end sub getNames
print join ",", getNames " Hello world this is a good test", 5;
>> Hello,world,this,is,a
If there is anything ambiguous to anybody how that works, I'll be glad to explain it to them. Noted that I'm still doing it with regexps. Other languages I would have used their native "trim" functions provided where possible.
Bollocks -->
I first tried this approach. This is your brain on regex. Kids, don't do regex.
This might be a good start
/([^\s]+
(\s[^\s]+
(\s[^\s]+
(\s[^\s]+
(\s[^\s]+|)
|)
|)
|)
)/
( Linebroken for clarity )
/([^\s]+(\s[^\s]+(\s[^\s]+(\s[^\s]+|)|)|))/
( Actual )
I've used [^\s]+ here instead of your A-Z combo for succintness, but the point is here the nested optional groups
ie:
(Hello( this( is( example))))
(Hello( this( is( example( two)))))
(Hello( this( is( better( example))))) three
(Hello( this( is()))))
(Hello( this()))
(Hello())
( Note: this, while being convoluted, has the benefit that it will match each name into its own group )
If you want readable code:
$word = '[^\s]+';
$regex = "/($word(\s$word(\s$word(\s$word(\s$word|)|)|)|)|)/";
( it anchors around the (capture|) mantra of "get this, or get nothing" )
#Sir Psycho : Be careful about your assumptions here. What about hyphenated names? Dotted names (e.g. Brian R. Bondy) and so on?
Here's the answer that you're most likely looking for:
^[a-zA-Z']+(\s[a-zA-Z']+){0,4}$
That says (in English): "From start to finish, match one or more letters, there can also be a space followed by another 'name' up to four times."
BTW: Why do you want them to have apostrophes anywhere in the name?
^([a-zA-Z']+\s){0,4}[a-zA-Z']+$
This assumes you want 4 spaces inside this string (i.e. you have trimmed it)
Edit: If you want 4 spaces anywhere I'd recommend not using regex - you'd be better off using a substr_count (or the equivalent in your language).
I also agree with pipTheGeek that there are so many different ways of writing names that you're probably best off trusting the user to get their name right (although I have found that a lot of people don't bother using capital letters on ecommerce checkouts).
Match multiple whitespace followed by two characters at the end of the line.
Related problem ----
From a string, remove trailing 2 characters preceded by multiple white spaces... For example, if the column contains this string -
" 'This is a long string with 2 chars at the end AB "
then, AB should be removed while retaining the sentence.
Solution ----
select 'This is a long string with 2 chars at the end AB' as "C1",
regexp_replace('This is a long string with 2 chars at the end AB',
'[[[:space:]][a-zA-Z][a-zA-Z]]*$') as "C2" from dual;
Output ----
C1
This is a long string with 2 chars at the end AB
C2
This is a long string with 2 chars at the end
Analysis ----
regular expression specifies - match and replace zero or more occurences (*) of a space ([:space:]) followed by combination of two characters ([a-zA-Z][a-zA-Z]) at the end of the line.
Hope this is useful.