I am not a C# programmer & need help. I have some questions:
when I have the string text='My car is nice', then what would be the output of the following lines:
(1) text.Substring(1,1);
(2) text.Substring(6,1);
(3) text.Substring(1,4).Replace('c','a');
(4) text.Substring(1,10).Replace('a','b').Replace(' ','t');
My conclusions are:
(1) 'y'
(2) ' is nice M' <== here, I started from 6 until 1 (or do I need to swap 1&6?)
(3) 'y c'
(4) 'ytcbrtist' <== here I replaced a with b & the space lines with t
I hope someone can help.
Best regards,
If you look at the doc of String.Substring Method (Int32, Int32) it says that:
public string Substring(
int startIndex,
int length
)
Then:
(1) text.Substring(1,1);
(2) text.Substring(6,1);
(3) text.Substring(1,4).Replace('c','a');
(4) text.Substring(1,10).Replace('a','b').Replace(' ','t');
(1) 'y' // Indice 1 length 1
(2) ' ' // Indice 6 length 1
(3) 'y aa' // Indice 1 length 4 and replacements
(4) 'ytcbrtistn'// Indice 1 length 10 and replacements
See it live
1)'y' OK
2)' ' The sixth character is 'r'. And the next one is space ' '.
3)'y aa' . You are taking 4 chars starting from first. It's 'y ca' . Later You replace c with a.
4)'ytcbrtistn' . You take 10 chars starting from 2nd one. 'y car is n' . You replace a with b -> 'y cbr is n' . Later replace space with t.
Related
I'm not an expert on regex and need some help to set up one.
I'm using Powershell and its [regex] type, which is a C# class, the final objective is to read a toml file (sample data at the bottom, or use this link to regex101), in which I need to:
match some values (values between "__")
ignore comments. (a comment starts with "#")
To match the values and put them in a capture group the following regex works:
match the template value (values between "__" ):
__(?<tokenName>[\w\.]+)__
I also want to ignore the commented lines, and I came up with this:
Ignore lines that start with a comment (even if "#" is preceded by spaces or tabs):
^(?!\s*\t*#).*
The problem starts when I put them together
^(?!\s*\t*#).*__(?<tokenName>[\w\.]+)__
this expression has the following problems:
up to one match per line, the last one (ie: in the line with "Prop5 = ..." I get one match instead of two)
Comments at the end of a line are not considered (ie: line with "Prop4 = ..." has two matches instead of one)
I've also tried to
add this at the end of the expression, it should stop the match on the first occurrence of the character
[^#]
add this at the beginning, which should check if the matched string has the given char before it and exclude it
(?<!^#)
This is a sample of my data
#templateFile
[Agent]
Prop1 = "__Data.Agent.Prop1__"
Prop2 = [__Data.Agent.Prop2__]
#I'm a comment
#Prop3 = "__NotUsed__"
Prop4 = [__Data.Agent.Prop4__] #sample usage comment __Data.Agent.xxx__
Prop5 = ["__Data.Agent.Prop5a__","__Data.Agent.Prop5b__"]
I think the easier solution will be to match the given string, only if there is no "#" before it on the same line.
Is it possible?
EDIT:
The first expression proposed by #the-fourth-bird works perfectly, it just needs the multiline modifier to be specified.
The final (runnable) result looks like this in PowerShell.
[regex]$reg = "(?m)(?<!^.*#.*)__(?<tokenName>[\w.]+)__"
$text = '
#templateFile
[Agent]
Prop1 = "__Data.Agent.Prop1__"
Prop2 = [__Data.Agent.Prop2__]
Prop5 = ["__Data.Agent.Prop5a__","__Data.Agent.Prop5b__"]
#a comment
#Prop3 = "__Data.Agent.Prop3__"
Prop4 = [__Data.Agent.Prop4__] #sample usage comment __Data.Agent.xxx__
'
$reg.Matches($text) | Format-Table
#This returns
Groups Success Name Captures Index Length Value
------ ------- ---- -------- ----- ------ -----
{0, tokenName} True 0 {0} 31 20 __Data.Agent.Prop1__
{0, tokenName} True 0 {0} 62 20 __Data.Agent.Prop2__
{0, tokenName} True 0 {0} 94 21 __Data.Agent.Prop5a__
{0, tokenName} True 0 {0} 118 21 __Data.Agent.Prop5b__
{0, tokenName} True 0 {0} 194 20 __Data.Agent.Prop4__
I think you could make use of infinite repetition to check if what precedes does not contain a # to also account for the comment in Prop4
(?<!^.*#.*)__(?<tokenName>[\w.]+)__
.Net regex demo
If Prop4 should have 2 matches, you might use:
(?<!^[ \t]*#.*)__(?<tokenName>[\w.]+)__
.NET regex demo
Both expressions needs the multiline modifier to work properly.
it can be specified inline by adding (?m) at the beginning. (or by specifying it in a constructor that supports it)
(?m)(?<!^.*#.*)__(?<tokenName>[\w.]+)__
I am trying to get all the possible order numbers for example on a given chunk of text. Order number usually starts with 104* and character limit 0f 10. However I was not able to get my desired outcome.
Here is the sample chunk of text.
05.12.17 PRZELEW PRZYCHODZACY 05.12.17 1,408.10 Referencje : PL0INE117339IZFN Nr Ref: 4339429172 Tytuł Płatnosci: 400481
1048432317, 400470 104843231 6 Kontr. : GDANSKDIS SP. Z O.O.
UL. OBRONCÓW WYBRZEZA 1 80-398 GDANSK POLAND Nr Banku:
18400007 SG Centrala Nr Rachunku: 31184000072413423008101119
Data Stempla 171205 Kwota Przekazu: 1,408.10 PLN Info Code;
0002794237
Some input are like these:
05.12.17 PRZELEW PRZYCHODZACY 05.12.17 316,082.18 Referencje : PL0INE117339BHBU Nr Ref: 4339079115 Tytuł Płatnosci: ID
0001817374 ZA1048418311 1 0484240771048423894 10484238 95AWIZO
Z DNIA 05.12.17 Kontr. : ZABKA POLSKA SPÓŁKA AKCYJNA PL
ANDERSA 7 61-894 POZNAN Nr Banku: 12402076 PEKAO Centrum
Rozliczeniow Nr Rachunku: 94124017471111001003042253 Data
Stempla 171205 Kwota Przekazu: 316,082.18 PLN
Also like this:
05.12.17 PRZELEW PRZYCHODZACY 05.12.17 999,429.47 Referencje : PL0INE117339LJBU Nr Ref: 4339548267 Tytuł Płatnosci:
PY01832649 1048432358 1048432351 10 48432466 1048432560 1048432594
1048 432267 1048432353 1048432450 104843 2360 1048432577
1048432391/KOR Kontr. : EUROCASH S.A. UL. WISNIOWA 11
62-052 KOMORNIKI Nr Banku: 10500028 ING Bank Slaski S.A. Nr
Rachunku: 73105000861000002334209315 Data Stempla 171205 Kwota
Przekazu: 999,429.47 PLN Info Code; 0000193176
The code I used is simple as this: \b104\d*
My result from the first input was:
1048432317
and
104843231
The last result was lacking in number as you can see, the last digit was in the next line.
My expected result is a regex that will able to extract all those order numbers without getting cut because the next digit was on the next line or sometimes order number getting cut.
You don't need regex, you can do that with simple string methods and readable LINQ:
List<string> orderNumberList = text.Replace(Environment.NewLine, "")
.Split(new char[] { }, StringSplitOptions.RemoveEmptyEntries)
.Where(word => word.StartsWith("104") && word.Length <= 10)
.ToList();
Your sample text blocks contain these 10 numbers:
[0] "1048432358"
[1] "1048432351"
[2] "1048432466"
[3] "1048432560"
[4] "1048432594"
[5] "1048432267"
[6] "1048432353"
[7] "1048432450"
[8] "1048432360"
[9] "1048432577"
Edit:
Sorry not using a code, I just need help with the regular expression
itself.
Saw this too late. Maybe better provide such informations in the question itself
It seems, you are looking for something like this:
string source =
#"05.12.17 PRZELEW PRZYCHODZACY 05.12.17 999,429.47
Referencje : PL0INE117339LJBU
Nr Ref: 4339548267
Tytuł Płatnosci: PY01832649 1048432358 1048432351 10
48432466 1048432560 1048432594 1048
432267 1048432353 1048432450 104843
2360 1048432577 1048432391/KOR
Kontr. : EUROCASH S.A.
UL. WISNIOWA 11
62-052 KOMORNIKI
Nr Banku: 10500028 ING Bank Slaski S.A.
Nr Rachunku: 73105000861000002334209315
Data Stempla 171205
Kwota Przekazu: 999,429.47 PLN
Info Code; 0000193176";
// We have to get rid of new lines and curret returns
var text = source
.Replace("\r", "")
.Replace("\n", "");
// pattern: we want 10 digits in total (3 for "104" and 7 for the rest part)
var result = Regex.Matches(text, #"\b104[0-9]{7}")
.OfType<Match>()
.Select(match => match.Value)
.ToArray();
I trying to use a regex command with loop over regex expression but is slow for files greater than 500 kb
please help me
using System;
using System.IO;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string Value3 =#"((#40y#.*?xlrz)(.*?)(#41y#[\s\S\r\n]*?)(\2))";
var match = Regex.Match(File.ReadAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt") , Value3);
while (match.Success)
{
var match2 = Regex.Match(File.ReadAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt") , Value3);
Regex rgx = new Regex(Value3);
match = match2;
string strFile3 = rgx.Replace(File.ReadAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt") , "$1$5$3+", 1);
File.WriteAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt", strFile3);
File.WriteAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\backupregex.txt", string.Concat(File.ReadAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\backupregex.txt") , strFile3.Substring(0, match2.Index +match2.Length)));
File.WriteAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt", strFile3.Substring(match2.Index +match2.Length, strFile3.Length - match2.Index - match2.Length ));
strFile3 = null;
int oldCacheSize = Regex.CacheSize;
Regex.CacheSize= 0;
GC.Collect();
Regex.CacheSize = oldCacheSize;
}
}
}
how can solve please help me
i have a loop each replace of this loop regex get a string of 10mb and make one replacement but this process is too slow , exist any method for solve this problem
when the file is small , regex process each replace fast –
hi my command divide the string in two then use the second string and find a word near at the begin of string then use the index and match lenght for divide the new string and repeat the same process in a loop –
the regex command find the string fast with string small 500 kb
but for string large 1mb this turn slow
word1 word2 word3 replace
word1 word2 word3 replace1
word1 word2 word3 replace2
output
word1 word2 word3 replace
word1 word2 word3 replace+replace1
word1 word2 word3 replace+replace1+replace2
002-0759586-1#39y#REPARTO 01#40y#002-075958655xlrz10,4#41y##42y#-10.20
002-0759586-2#39y#REPARTO 01#40y#002-0759586xlrz54#41y#0#42y#
002-0759586-2#39y#REPARTO 01#40y#002-0759586xlrz56#41y#0#42y#
002-0759586-2#39y#REPARTO 01#40y#002-0759586xlrz57#41y#0#42y#
An attempt at an answer.
Problem 1. Regex
Existing:
( # (1 start)
( \# 40y \# .*? xlrz ) # (2)
( .*? ) # (3)
( \# 41y \# [\s\S\r\n]*? ) # (4)
( \2 ) # (5)
) # (1 end)
What it should be:
( # (1 start)
\# 40y \#
.*?
xlrz
) # (1 end)
( .*? ) # (2)
\# 41y \#
(?s: .*? )
\1
Capture group changes (old -> new):
1 -> 0
2 -> 1
3 -> 2
4 -> N/A
5 -> 1
Benchmark
Regex1: ((\#40y\#.*?xlrz)(.*?)(\#41y\#[\s\S\r\n]*?)(\2))
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 1
Elapsed Time: 4.04 s, 4042.77 ms, 4042771 µs
Regex2: ((\#40y\#.*?xlrz)(.*?)\#41y\#(?s:.*?)\2)
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 1
Elapsed Time: 1.91 s, 1913.65 ms, 1913650 µs
The general regex problem:
You are delimiting a string with what is captured in Group 1.
The problem is group 1 contains a middle sub-expression .*? which is
a hole that backtracking drives a truck through.
This probably can't be avoided, but since you are only matching once each
time, it might not make a difference.
Problem 2. Regex
Never remake a regex within a loop construct. Make it once outside the loop.
If you feel you need to use the same regex twice within the same loop,
red flags should go up as this is never necessary.
If you do however, make two separate regex var's of the same regex.
I.e. Regex rgx1 = new Regex(Value3); Regex rgx2 = new Regex(Value3);
then access the object instance methods (not class methods) for matching.
Problem 3. Program flow
You are manipulating a single file, C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt
Within a loop, you constantly read it, manipulate it, then write it.
This is problematic at best.
The only reason to ever do this would be to make temporary copies, not what
you're doing with it now.
If you think for some reason you're saving memory resources, you'd be mistaken.
For one, the stack is of limited size as compared to the heap.
Once you have the ORIGINAL file read into a string variable, do all the
operations on that string, then as a last step, write it out to the file.
This part of your code is inappropriate, but used as an example:
string strFile3 = rgx.Replace(File.ReadAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt") , "$1$5$3+", 1);
File.WriteAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt", strFile3);
File.WriteAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\backupregex.txt", string.Concat(File.ReadAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\backupregex.txt") , strFile3.Substring(0, match2.Index +match2.Length)));
File.WriteAllText(#"C:\Users\diego\Desktop\pruebatabladinamica\pruebassregex.txt", strFile3.Substring(match2.Index +match2.Length, strFile3.Length - match2.Index - match2.Length ));
All can be reduced to the manipulation of strFile3 without doing the
intense overhead of reading and writing and thrashing the disk.
In actuality, this is what is causing the performance lag you see on a larger
file.
End of attempt ..
I have the following problem:
I have a file which is nearly 500mb big. Its text, all in one line. The text is seperated with a virtual line ending, its called ROW_DEL and is in the text like this:
this is a line ROW_DEL and this is a line
now I need to make the following, I want to split this file into its lines so I get a file like this:
this is a line
and this is a line
the problem, even if I open it with the windows text editor, it breakes because the file is to big.
Is it possible to split this file like I mentioned with C#, Java or Python? Whats would be the best soultion to dont overkill my cpu.
Actually 500mb of text is not that big, it's just that notepad sucks. You probably don't have sed available since you're on windows but at least try naive solution in python, I think it will work fine:
import os
with open('infile.txt') as f_in, open('outfile.txt', 'w') as f_out:
f_out.write(f_in.read().replace('ROW_DEL ', os.linesep))
Read this file in chunks, for example use StreamReader.ReadBlock in c#. You can set the maximum number of characters to read there.
For each readed chunk you can replace ROW_DEL to \r\n and append it to new file.
Just remember to increase current index by the number of character you just read.
Here's my solution.
Easy in the principle (ŁukaszW.pl gave it) but not so easy to code if one wants to take care of peculiar cases (which ŁukaszW.pl did not).
The peculiar cases are when the separator ROW_DEL is splitted in two of the read chunks (as I4V pointed out), and even more subtlely if there are two contiguous ROW_DEL of which the second is splitted in two read chunks.
Since ROW_DEL is longer than any of the possible newlines ('\r', '\n', '\r\n') , it can be replaced in place in the file by the newline used by the OS. That's why I choosed to rewrite the file in itself.
For that I use mode 'r+', it doesn't create a new file.
It's also absolutely mandatory to use a binary mode 'b'.
The principle is to read a chunk (in real life its size will be 262144 for example) and x additional characters, wher x is the length of the separator -1.
And then to examine if the separator is present in the end of the chunk + the x characters.
Accoridng if it is present or not, the chunk is shortened or not before the transformation of the ROW_DEL is performed, and rewritten in place.
The nude code is:
text = ('The hospital roommate of a man infected ROW_DEL'
'with novel coronavirus (NCoV)ROW_DEL'
'—a SARS-related virus first identified ROW_DELROW_DEL'
'last year and already linked to 18 deaths—ROW_DEL'
'has contracted the illness himself, ROW_DEL'
'intensifying concerns about the ROW_DEL'
"virus's ability to spread ROW_DEL"
'from person to person.')
with open('eessaa.txt','w') as f:
f.write(text)
with open('eessaa.txt','rb') as f:
ch = f.read()
print ch.replace('ROW_DEL','ROW_DEL\n')
print '\nlength of the text : %d chars\n' % len(text)
#==========================================
from os.path import getsize
from os import fsync,linesep
def rewrite(whichfile,sep,chunk_length,OSeol=linesep):
if chunk_length<len(sep):
print 'Length of second argument, %d , is '\
'the minimum value for the third argument'\
% len(sep)
return
x = len(sep)-1
x2 = 2*x
file_length = getsize(whichfile)
with open(whichfile,'rb+') as fR,\
open(whichfile,'rb+') as fW:
while True:
chunk = fR.read(chunk_length)
pch = fR.tell()
twelve = chunk[-x:] + fR.read(x)
ptw = fR.tell()
if sep in twelve:
pt = twelve.find(sep)
m = ("\n !! %r is "
"at position %d in twelve !!" % (sep,pt))
y = chunk[0:-x+pt].replace(sep,OSeol)
else:
pt = x
m = ''
y = chunk.replace(sep,OSeol)
pos = fW.tell()
fW.write(y)
fW.flush()
fsync(fW.fileno())
if fR.tell()<file_length:
fR.seek(-x2+pt,1)
else:
fW.truncate()
break
rewrite('eessaa.txt','ROW_DEL',14)
with open('eessaa.txt','rb') as f:
ch = f.read()
print '\n'.join(repr(line)[1:-1] for line in ch.splitlines(1))
print '\nlength of the text : %d chars\n' % len(ch)
To follow the execution, here's another code that prints messages all along:
text = ('The hospital roommate of a man infected ROW_DEL'
'with novel coronavirus (NCoV)ROW_DEL'
'—a SARS-related virus first identified ROW_DELROW_DEL'
'last year and already linked to 18 deaths—ROW_DEL'
'has contracted the illness himself, ROW_DEL'
'intensifying concerns about the ROW_DEL'
"virus's ability to spread ROW_DEL"
'from person to person.')
with open('eessaa.txt','w') as f:
f.write(text)
with open('eessaa.txt','rb') as f:
ch = f.read()
print ch.replace('ROW_DEL','ROW_DEL\n')
print '\nlength of the text : %d chars\n' % len(text)
#==========================================
from os.path import getsize
from os import fsync,linesep
def rewrite(whichfile,sep,chunk_length,OSeol=linesep):
if chunk_length<len(sep):
print 'Length of second argument, %d , is '\
'the minimum value for the third argument'\
% len(sep)
return
x = len(sep)-1
x2 = 2*x
file_length = getsize(whichfile)
with open(whichfile,'rb+') as fR,\
open(whichfile,'rb+') as fW:
while True:
chunk = fR.read(chunk_length)
pch = fR.tell()
twelve = chunk[-x:] + fR.read(x)
ptw = fR.tell()
if sep in twelve:
pt = twelve.find(sep)
m = ("\n !! %r is "
"at position %d in twelve !!" % (sep,pt))
y = chunk[0:-x+pt].replace(sep,OSeol)
else:
pt = x
m = ''
y = chunk.replace(sep,OSeol)
print ('chunk == %r %d chars\n'
' -> fR now at position %d\n'
'twelve == %r %d chars %s\n'
' -> fR now at position %d'
% (chunk ,len(chunk), pch,
twelve,len(twelve),m, ptw) )
pos = fW.tell()
fW.write(y)
fW.flush()
fsync(fW.fileno())
print (' %r %d long\n'
' has been written from position %d\n'
' => fW now at position %d'
% (y,len(y),pos,fW.tell()))
if fR.tell()<file_length:
fR.seek(-x2+pt,1)
print ' -> fR moved %d characters back to position %d'\
% (x2-pt,fR.tell())
else:
print (" => fR is at position %d == file's size\n"
' File has thoroughly been read'
% fR.tell())
fW.truncate()
break
raw_input('\npress any key to continue')
rewrite('eessaa.txt','ROW_DEL',14)
with open('eessaa.txt','rb') as f:
ch = f.read()
print '\n'.join(repr(line)[1:-1] for line in ch.splitlines(1))
print '\nlength of the text : %d chars\n' % len(ch)
There's some subtlety in the treatment of the ends of the chunks in order to detect if ROW_DEL straddles on two chunks and if there are two ROW_DEL contiguous. That's why I took a long time to post my solution: I finally was obliged to write fR.seek(-x2+pt,1) and not only fR.seek(-2*x,1) or fR.seek(-x,1) according if sep is straddling or not (2*x is x2 in the code, with ROW_DEL x and x2 are 6 and 12). Anybody interested by this point will examine it by changing the codes in the sections accoridng if 'ROW_DEL' is in twelve or not.
Declare #CustTotalCount as int
Declare #CustMatchCount as int
select #CustTotalCount = count(*) from ENG_CUSTOMERTALLY
select #CustMatchCount = count(*) from Task where MPDReference in(
select ENG_CUSTOMERTALLY_CUSTOMERTASKNUMBER from dbo.ENG_CUSTOMERTALLY)
if(#CustTotalCount>#CustMatchCount)
select distinct
substring(ENG_CUSTOMERMYCROSS_MYTECHNIC_TASK_NO, charindex('-', ENG_CUSTOMERMYCROSS_MYTECHNIC_TASK_NO)
+ 1, 1000)
from dbo.ENG_CUSTOMERMYCROSS where
ENG_CUSTOMERMYCROSS_CUSTOMER_NUMBER in(
select ENG_CUSTOMERTALLY_CUSTOMERTASKNUMBER from ENG_CUSTOMERTALLY1
except
select MPDReference from Task )
I can convert
- A320-200001-01-1(1)
- A320-200001-02-1(2)
- A320-200001-01-1(2)
- A320-200001-01-1(1)
- A320-200001-01-1(2)
- A320-200001-02-1(1)
TO
- 200001-01-1(1)
- 200001-02-1(2)
- 200001-01-1(2)
- 200001-01-1(1)
- 200001-01-1(2)
- 200001-02-1(1)
But I need to :
- 200001-01-1
- 200001-02-1
- 200001-01-1
- 200001-01-1
- 200001-01-1
- 200001-02-1
How can I do that in SQL and C#?
Is the pattern always the same, if so you could just use SUBSTRING to pull out the bit you want.
EDIT: To take in additional stuff asked in How can i use substring in SQL?
You could
SELECT DISTINCT SUBSTRING(....) FROM ...
as answered above, use the SUBSTRING method like you are but use a length of 11 instead of 1000 as long as the data is always in the format you show above.
In C# it would be:
string s = "A320-20001-01-1(1)";
string result = s.Substring(s.IndexOf('-'), 11);
again this is assuming the part you want is always 11 characters. Otherwise if it is always the first '(' you want to end before, you the IndexOf method/function again to find the end index and subtract the first index
Try substring and len, this sample cuts first 6 and last 4 (4 = 10-6) chars
declare #var varchar(50)
set #var = 'A320-200001-01-1(1)
select substring(#var, 6, len(#var) - 10)
output: 200001-01
In c#, functions are similar, exept zero-based index:
string var = "A320-200001-01-1(1)";
var = var.Substring(5, var.Length - 8);
Console.WriteLine(var);
Here's a technique that uses PATINDEX, which can use wild cards.
SUBSTRING(ENG_CUSTOMERMYCROSS_MYTECHNIC_TASK_NO,
PATINDEX('%[0-9]%', ENG_CUSTOMERMYCROSS_MYTECHNIC_TASK_NO),
PATINDEX('%(%', ENG_CUSTOMERMYCROSS_MYTECHNIC_TASK_NO)
- PATINDEX('%[0-9]%', ENG_CUSTOMERMYCROSS_MYTECHNIC_TASK_NO)
)
The start for your substring is the position of the first numeric value (%[0-9]%). The length value is the position of the first parenthesis ('%(%') less the starting position.