Regex to extract value at fixed position index - regex

I have the following string of characters:
73746174652C313A312C310D
|
- extract the value at this position
I would like to extract the value 1 (the 1 at the end of the string) using regex.
So basically a regex that acts as a charAt(index).
I need this solution for a 3rd party application that only supports regular expressions. Note that the application cannot access capture groups and does not support negative lookbehinds.

In C#:
(?<=^.{21})(.)
in JS:
/.(?=.{2}$)/

You could try:
(?<=^.{21}).
It won't work in Javascript, but perhaps it will work in your app.
It means: a single character preceded (?<= ... ) by the beginning of the string ^ plus 21 characters .{21} . So, in the end, it returns the 22th character.

The 22nd character is in capture group 1.
/^.{21}(.)/
But what system are you in that requires this instead of normal string processing?

Depends how you want to match it ( x distance from the beginning or x distance from the end )
/(.).{2}$/ Third from the end (capturing group 1)
/^.{21}(.)/ 22nd character (capturing group 1)
//PHP
$str = '73746174652C313A312C310D';
$char = preg_replace('/(.).{2}$/','$1',$str); //3rd from last
preg_match('/(.).{2}$/',$str,$chars); //3rd from last
$char = $chars[1];
preg_match('/^.{21}(.)/',$str,$chars); //22nd character
$char = $chars[1];
//JS
var str = '73746174652C313A312C310D';
var ch = str.replace(/(.).{2}$/,'$1'); //3rd from last
var ch = str.match(/(.).{2}$/)[1]; //3rd from last
var ch = str.match(/^.{21}(.)/)[1]; //22nd character
If you're having to use the result of the First match: bit of your tool, run it twice:
73746174652C313A312C310D - ^.{21}. = 73746174652C313A312C31
73746174652C313A312C31 - .$ = 1

Related

match everything but a given string and do not match single characters from that string

Let's start with the following input.
Input = 'blue, blueblue, b l u e'
I want to match everything that is not the string 'blue'. Note that blueblue should not match, but single characters should (even if present in match string).
From this, If I replace the matches with an empty string, it should return:
Result = 'blueblueblue'
I have tried with [^\bblue\b]+
but this matches the last four single characters 'b', 'l','u','e'
Another solution:
(?<=blue)(?:(?!blue).)+(?=blue|$)|^(?:(?!blue).)+(?=blue|$)
Regex demo
If you regex engine support the \K flag, then we can try:
/blue\K|.*?(?=blue|$)/gm
Demo
This pattern says to match:
blue match "blue"
\K but then forget that match
| OR
.*? match anything else until reaching
(?=blue|$) the next "blue" or the end of the string
Edit:
On JavaScript, we can try the following replacement:
var input = "blue, blueblue, b l u e";
var output = input.replace(/blue|.*?(?=blue|$)/g, (x) => x != "blue" ? "" : "blue");
console.log(output);

How do I replace the nth occurrence of a special character, say, a pipe delimiter with another in Scala?

I'm new to Spark using Scala and I need to replace every nth occurrence of the delimiter with the newline character.
So far, I have been successful at entering a new line after the pipe delimiter.
I'm unable to replace the delimiter itself.
My input string is
val txt = "January|February|March|April|May|June|July|August|September|October|November|December"
println(txt.replaceAll(".\\|", "$0\n"))
The above statement generates the following output.
January|
February|
March|
April|
May|
June|
July|
August|
September|
October|
November|
December
I referred to the suggestion at https://salesforce.stackexchange.com/questions/189923/adding-comma-separator-for-every-nth-character but when I enter the number in the curly braces, I only end up adding the newline after 2 characters after the delimiter.
I'm expecting my output to be as given below.
January|February
March|April
May|June
July|August
September|October
November|December
How do I change my regular expression to get the desired output?
Update:
My friend suggested I try the following statement
println(txt.replaceAll("(.*?\\|){2}", "$0\n"))
and this produced the following output
January|February|
March|April|
May|June|
July|August|
September|October|
November|December
Now I just need to get rid of the pipe symbol at the end of each line.
You want to move the 2nd bar | outside of the capture group.
txt.replaceAll("([^|]+\\|[^|]+)\\|", "$1\n")
//val res0: String =
// January|February
// March|April
// May|June
// July|August
// September|October
// November|December
Regex Explained (regex is not Scala)
( - start a capture group
[^|] - any character as long as it's not the bar | character
[^|]+ - 1 or more of those (any) non-bar chars
\\| - followed by a single bar char |
[^|]+ - followed by 1 or more of any non-bar chars
) - close the capture group
\\| - followed by a single bar char (not in capture group)
"$1\n" - replace the entire matching string with just the first $1 capture group ($0 is the entire matching string) followed by the newline char
UPDATE
For the general case of N repetitions, regex becomes a bit more cumbersome, at least if you're trying to do it with a single regex formula.
The simplest thing to do (not the most efficient but simple to code) is to traverse the String twice.
val n = 5
txt.replaceAll(s"(\\w+\\|){$n}", "$0\n")
.replaceAll("\\|\n", "\n")
//val res0: String =
// January|February|March|April|May
// June|July|August|September|October
// November|December
You could first split the string using '|' to get the array of string and then loop through it to perform the logic you want and get the output as required.
val txt = "January|February|March|April|May|June|July|August|September|October|November|December"
val out = txt.split("\\|")
var output: String = ""
for(i<-0 until out.length -1 by 2){
val ref = out(i) + "|" + out(i+1) + "\n"
output = output + ref
}
val finalout = output.replaceAll("\"\"","") //just to remove the starting double quote
println(finalout)

Regex find most center

I need to manully hyphante words that are too long. Using hyphen.js, I get soft hyphens between every syllable, like below.
I want to find the hyphen closes to the middle. All words will be more than 14 characters long. Regex that works in https://regex101.com/ or node/js example.
Basically, find the middle character excluding hyphens, check if there is a hyphen there, then step backwards one step and then forwards one step, then backwards to steps etc.
re-spon-si-bil-i-ties => [re-spon-si,-bil-i-ties]
com-pe-ten-cies. => [com-pe,-ten-cies.]
ini-tia-tives. => [ini-tia,-tives]
vul-ner-a-bil-i-ties => [vul-ner-a,-bil-i-ties]
Here's a simple js approach based on string splitting. There could be a binary search style algorithm as you mentioned which would avoid the array allocation but that seems overkill for these small data sets.
function halve(str) {
var right = str.split('-');
var left = right.splice(0, Math.ceil(right.length / 2));
return right.length > 0 ? [left.join('-'), '-' + right.join('-')] : left;
}
console.log(halve('re-spon-si-bil-i-ties'));
console.log(halve('com-pe-ten-cies.'));
console.log(halve('ini-tia-tives.'));
console.log(halve('vul-ner-a-bil-i-ties'));
console.log(halve('none')); // no hyphens returns ["none"]
You can work this out with this method:
Get middle point of string
From the middle point, and checking each character in both directions (left from middle, right from middle) check if that position is the - character. Set the index to the first such match.
If it matches that character, stop the loop and split the string on that index, otherwise return the original word.
words = [
're-spon-si-bil-i-ties',
'com-pe-ten-cies.',
'ini-tia-tives.',
'vul-ner-a-bil-i-ties',
'test',
'-aa',
'aa-'
];
split = '-'
for(word of words) {
m=Math.floor(word.length/2),offset=0,i=null
do{
if(word[m-offset] == split) i = m-offset
else if(word[m+offset] == split) i = m+offset
else offset++
}while(offset<=m && i == null)
if(i!=null && i>0) console.log([word.substring(0,i),word.substring(i)])
else console.log(word)
}
You can achieve this with:
var words = [
're-spon-si-bil-i-ties',
'com-pe-ten-cies.',
'ini-tia-tives.',
'vul-ner-a-bil-i-ties',
're-ports—typ-i-cal-ly',
'none'
];
for(var i = 0; i < words.length; ++i){
var matches = words[i]
.match(
new RegExp(
'^((?:[^-]+?-?){' // Start the regex
+parseInt(
words[i].replace( /-/g, '' ).length/2 // Round down the halfway point of this word's length without the hyphens
)
+'})(-.+)?$' // End the regex
)
)
.slice( 1 ); // Remove position 0 because it is the entire word
console.log( matches );
}
Regex explanation for re-spon-si-bil-i-ties:
^((?:[^-]+?-?){8})(-.+)$
^( - start the capture group leading up to the half way point
(?:[^-]+?-?) - find everything not a hyphen with an optional hyphen after it. Make the hyphen optional so that the second capture group can greedily claim it
{8} - 8 times; this will get us half way
) - close the half way capture group
(-.+)?$ - greedily get the hyphen and everything after it till the end of the string

How to find any non-digit characters using RegEx in ABAP

I need a Regular Expression to check whether a value contains any other characters than digits between 0 and 9.
I also want to check the length of the value.
The RegEx I´ve made: ^([0-9]\d{6})$
My test value is: 123Z45 and 123456
The ABAP code:
FIND ALL OCCURENCES OF REGEX '^([0-9]\d{6})$' IN L_VALUE RESULTS DATA(LT_RESULTS).
I´m expecting a result in LT_RESULTS, when I´m testing the first test value '123Z45', because there is a non-digit character.
But LT_RESULTS is in nearly every test case empty.
Your expression ^([0-9]\d{6})$ translates to:
^ - start of input
( - begin capture group
[0-9] - a character between 0 and 9
\d{6} - six digits (digit = character between 0 and 9)
) - end capture group
$ - end of input
So it will only match 1234567 (7 digit strings), not 123456, or 123Z45.
If you just need to find a string that contains non digits you could use the following instead: ^\d*[^\d]+\d*$
* - previous element may occur zero, one or more times
[^\d] - ^ right after [ means "NOT", i.e. any character which is not a digit
+ - previous element may occur one or more times
Example:
const expression = /^\d*[^\d]+\d*$/;
const inputs = ['123Z45', '123456', 'abc', 'a21345', '1234f', '142345'];
console.log(inputs.filter(i => expression.test(i)));
You can also use this character class if you want to extract non-digit group:
DATA(l_guid) = '0074162D8EAA549794A4EF38D9553990680B89A1'.
DATA(regx) = '[[:alpha:]]+'.
DATA(substr) = match( val = l_guid
regex = regx
occ = 1 ).
It finds a first occured non-digit group of characters and shows it.
If you want to just check if they are exists or how much of them reside in your string, count built-in function is your friend:
DATA(how_many) = count( val = l_guid regex = regx ).
DATA(yes) = boolc( count( val = l_guid regex = regx ) > 0 ).
Match and count exist since ABAP 7.50.
If you don't need a Regular Expression for something more complex, ABAP has some nice comparison operators CO (Contains Only), CA, NA etc for you. Something like:
IF L_VALUE CO '0123456789' AND STRLEN( L_VALUE ) = 6.

How to Split the message in as3?

Hi, am trying to split the word rtmp://xx.yyy.in/sample/test?22082208,False#&all this word.The word sample is dynamically added I don't know the count.
I want to split /sample/ how to do this kindly help me?
You want the string.split() method
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/String.html#split%28%29
var array:Array = myString.split("/"); //returns an array of everything in between /
In your case this will return
[0]->?rtmp:/ [1]->xx.yy.in [2]->sample [3]->test?22082208,False#&all
If you're looking for everything aside from the test?22082208,False#&all part and your URL will always be in this format you can use string.lastIndexOf()
var pos:int = string.lastIndexOf("/", 0); //returns the position of the last /
var newString:String = string.substr(0, pos); //creates a new string starting at 0 and ending at the last index of /
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/String.html#substr%28%29
You can do this (and almost everything) with regex:
var input:String = "rtmp://xx.yyy.in/sample/test?22082208,False#&all";
var pattern:RegExp = /^rtmp:\/\/.*\/([^\/]*)\/.*$/;
trace(input.replace(pattern, "$1")); //outputs "sample"
Here is the regex in details:
^ : start of the string
rtmp:\/\/ first string to find "rtmp://"
.* anything
\/ first slash
([^\/]) capture everything but a slash until...
\/ ...second slash
.* anything
$ the end
Then $1 represents the captured group between the parenthesis.