Version:0.9 StartHTML:0000000105 EndHTML:0000171154 StartFragment:0000001037 EndFragment:0000171138
Program RegEx_Power_Tester_TRex3;
// Framework for RegEx tests TRex at EKON 16
// get the Box at: http://www.softwareschule.ch/maxbox.htm
//*********************************************************************
// logic REGEX ledwall example with objects, loc's=980, 28 intf, example 309ff
// first you define a size und pattern (word) and alter the pattern with
// the function shows Delphi RegEx, TRegEx Studio and Core Unit Regex;
// task: write the sentence in sequence: 'the world of TREX color!'
//*********************************************************************
Const PATTERNPAUSE = 350;
RUNPAUSE = 180;
COL = 5;
ROW = 7;
SIGNS = 36; //(37_[0..36]: Space, A..Z, 0..9)
LEFTBASE = 20;
TOPBASE = 30;
TEXTPATH = 'examples\outline3.txt';
AVIPATH = 'examples\cool.avi';
BITMAP = 'examples\citymax.bmp';
var
ppForm: TForm;
mylabel: TLabel;
pattern1: string;
labelList: TStringList;
psize: integer;
pattar: array[0..SIGNS] of shortstring;
mbitmap: TBitmap;
s1, c1: extended;
E: Exception;
procedure pauseLED(vpatt: shortstring); forward;
procedure LetShowRunVerify(apatt: string);
var i,x: integer;
o: TLabel;
begin
for x:= 0 to COL do begin
for i:= 1 to psize do begin
o:= TLabel(labelList.objects[i-1]);
if apatt[i] = '1' then o.color:= clblack
else o.color:= (clyellow);
end;
for i:= 1 to psize do begin //XCopy
apatt[i]:= apatt[i+1];
if (i mod COL = 0) then //!!
apatt[i]:= '0'
end;
Sleep(RUNPAUSE)
//if x= 4 then Break; //optimise if run
end;
//Application.Processmessages; //debug
end;
procedure LetShowRunVerify2(vpattern: string); //draft
var
i,x: integer;
o: TLabel;
pattern2: shortstring;
begin
for i:= 1 to 40 do
pattern2:= pattern2 + '0'; //Empty Space;
for i:= 1 to psize+1 do begin //recopy XCopy
if vpattern[i] = '1' then begin
pattern2[i+1]:= '1';
end;
end;
for x:= 0 to COL -1 do begin
for i:= 1 to psize do begin
//set next line of labels
o:= TLabel(labelList.objects[i-1]);
if pattern2[i] = '1' then o.color:= clblack
else o.color:= (clyellow);
end;
for i:= 1 to psize do begin //recopy
pattern2[i]:= pattern2[i+1];
if (i mod COL = 0) then //!!
pattern2[i]:= '0'
end;
//old
sleep(RUNPAUSE)
if x= 4 then break;
end;
//application.processmessages;
end;
procedure letShowVerify(vpattern: string);
var i: integer;
o: TLabel;
begin
for i:= 1 to psize do begin
o:= TLabel(labelList.objects[i-1]);
//o.caption:= inttostr(i);
if i <= length(vpattern) then
if vpattern[i] = '1' then o.color:= clblack
else o.color:= clyellow;
end;
//Runchar(vpattern)
//application.ProcessMessages;
end;
procedure Label1Click_EditPattern(Sender: TObject);
var o: TLabel;
sx: byte;
begin
//70 in begin sound
//showMessage(intToStr(TLabel(sender).tag))
sx:= TLabel(sender).tag;
o:= TLabel(labelList.objects[sx-1]);
//o.caption:= inttostr(i);
if o.color = clBlack then o.color:= clyellow
else o.color:= clblack;
end;
procedure pauseLED(vpatt: shortstring);
begin
sleep(PATTERNPAUSE);
letShowVerify(vpatt);
end;
procedure Label1DClick_WritePattern(Sender: TObject);
var i: byte;
st: shortstring;
o: TLabel;
begin
//70 in begin sound
st:= pattar[0];
for i:= 1 to psize do begin
o:= TLabel(labelList.objects[i-1]);
//o.caption:= inttostr(i);
if o.color = clBlack then st[i]:= '1'
else st[i]:= '0';
end;
//SetLEDConsole(st)
//writeln(st)
end;
procedure ShowLED_TestSeq;
var
pt0, pt11, tmpstr: shortstring;
il: integer;
begin
pt0:= '00000000000000000000000000000000000';
pt11:= '00100010101001111111011100111111100'; //hex store test 32+3=35
tmpstr:= pt11;
delete(tmpstr,4,32)
writeln('cut test '+tmpstr)
writeln(bintohex2(tmpstr)); //00000001
writeln(bintohex2(pt11)); //153FB9FC
writeln(tmpstr+hextobin2(bintohex2(pt11))); //test to store pattern as HEX
writeln(pt11)
pattern1:= '';
for il:= 0 to SIGNS do begin
letShowVerify(pattar[il]);
//writeln('pt'+inttostr(il))
pauseLED(pt0)
end;
end;
Procedure WriteLED_Set(sentence: string; arun: boolean); //draft
var il,a: byte;
begin
sentence:= Uppercase(sentence)
for il:= 1 to length(sentence) do begin
a:= Ord(sentence[il])-47; //ASCII 0=48 9=57
writeln(inttostr(a)) //debug
if (a>0) and (a<16) then begin
if arun then
letShowRunVerify(pattar[a])
else letShowVerify(pattar[a]);
end;
if (a>17) and (a<42) then begin //ASCII A=65 Z=90
if arun then
letShowRunVerify(pattar[a-7])
else letShowVerify(pattar[a-7]);
end;
if a>220 then begin
//if not arun then
pauseLED(pattar[0]);
end;
write(sentence[il]) //test to console
end;
end;
procedure FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13
then WriteLED_Set(pattern1, true);
if Key = #27 then ppForm.close;
end;
procedure CloseForm(Sender: TObject; var action: TCloseAction);
var i: integer;
begin
for i:= 1 to psize do
TLabel(labelList.objects[i-1]).Free;
action:= caFree;
writeln('free it label objects') //debug
end;
procedure loadPForm(vx, vy: integer);
begin
psize:= vx*vy
//constructor
ppform:= TForm.Create(self);
with ppform do begin
caption:= 'LEDBOX, click to edit, dblclick write out pattern'+
' Press <Return> to run the Sentence';
width:= (vx*psize)+ 10 + 300;
height:= (vy*psize)+ 30;
BorderStyle:= bsDialog;
Position:= poScreenCenter;
onKeyPress:= @FormKeyPress
//OnClick:= @Label1Click;
OnClose:= @closeForm;
Show;
end
end;
procedure InitPuzzle(vx: byte);
var i,x,y: integer;
begin
labelList:= TStringList.Create;
x:= 1;
y:= 1;
for i:= 1 to psize do begin
mylabel:= TLabel.Create(ppform);
with mylabel do begin
Parent:= ppForm;
color:= clyellow;
transparent:= false;
AutoSize:= false;
layout:= tlcenter;
alignment:= tacenter;
font.Size:= (psize div vx) + 12;
//font.Style:= [fsbold];
font.Color:= clyellow;
width:= psize; //+1 without raster
height:= psize;
Left:= (x-1)*(psize + 1);
Top:= (y-1)*(psize + 1);
//event handler to click!
OnClick:= @Label1Click_EditPattern;
OnDblClick:= @Label1DClick_WritePattern;
tag:= i; //save the position
end;
//set next line of labels
if (i mod vx = 0) then begin
x:= 1;
inc(y);
end else
inc(x);
//add labels to the list
labellist.instancesize
labelList.addObject(inttostr(i), mylabel);
end;
end;
procedure InitLED_SignPatterns; //add with 0 at the end
begin
pattar[0]:= '000000000000000000000000000000000000'; //Empty Space;
pattar[1]:= '001000101001010010100101001010001000'; //0
pattar[2]:= '001100111000010000100001000010000100'; //1
pattar[3]:= '011100001000010011100100001000011100'; //2
pattar[4]:= '011100001000010011100001000010011100'; //3
pattar[5]:= '001100101001010010100111100010000100'; //4
pattar[6]:= '011100100001100000100001000010011000'; //5
pattar[7]:= '001100100001000011100101001010001000'; //6
pattar[8]:= '011100001000010001000010000100001000'; //7
pattar[9]:= '011100101001010011100101001010011100'; //8
pattar[10]:= '011100101001010011100001000100010000'; //9
pattar[11]:= '001000101001010100011111110001100010'; //A;
pattar[12]:= '111001001010010111001001010010111000'; //B;
pattar[13]:= '001100100010000100001000001000001100'; //C;
pattar[14]:= '111001001010001100011000110010111000'; //D;
pattar[15]:= '111101000010000111101000010000111100'; //E;
pattar[16]:= '111111000010000111101000010000100000'; //F;
pattar[17]:= '001100100110000101111000101001001100'; //G;
pattar[18]:= '100011000110001111111000110001100010'; //H;
pattar[19]:= '001000010000100001000010000100001000'; //I;
pattar[20]:= '001110001000010000100001010010011000'; //J;
pattar[21]:= '100011001010100110001010010010100010'; //K;
pattar[22]:= '100001000010000100001000010000111110'; //L;
pattar[23]:= '110111010110101101011000110001100010'; //M;
pattar[24]:= '100011100110101100111000110001100010'; //N;
pattar[25]:= '001000101010001100011000101010001000'; //O;
pattar[26]:= '111001001010010100101110010000100000'; //P;
pattar[27]:= '011101000110001100011000101110000110'; //Q;
pattar[28]:= '111001001010010111001010010010100010'; //R
pattar[29]:= '011101000010000011000001000010111000'; //S
pattar[30]:= '111110010000100001000010000100001000'; //T
pattar[31]:= '100011000110001100011000111011011100'; //U
pattar[32]:= '100011000110001010100101000100001000'; //V
pattar[33]:= '100011000110101101011010110101010100'; //W
pattar[34]:= '100011000101010001000101010001100010'; //X
pattar[35]:= '100011101101010001000010000100001000'; //Y
pattar[36]:= '111110000100010001000100010000111110'; //Z
end;
procedure LetBitmap;
begin
mbitmap:= TBitmap.Create;
try
mbitmap.LoadFromFile(Exepath+BITMAP);
ppForm.Canvas.Draw(270,70, mbitmap);
finally
raiseException2;
//ppForm.Free;
end;
end;
//****************************** TRex Tester ********************************//
type
TDecorateURLsFlags = (
// describes, which parts of hyper-link must be included
// into VISIBLE part of the link:
durlProto, // Protocol (like 'ftp://' or 'http://')
durlAddr, // TCP address or domain name (like 'anso.da.ru')
durlPort, // Port number if specified (like ':8080')
durlPath, // Path to document (like 'index.htm')
durlBMark, // Book mark (like '#mark')
durlParam // URL params (like '?ID=2&User=13')
);
TDecorateURLsFlagSet = set of TDecorateURLsFlags;
const
URLTemplate =
'(?i)('
+ '(FTP|HTTP)://' // Protocol
+ '|www\.)' // trick to catch links without protocol by detecting start'www.'
+ '([\w\d\-]+(\.[\w\d\-]+)+)' // TCP addr or domain name
+ '(:\d\d?\d?\d?\d?)?' // port number
+ '(((/[%+\w\d\-\\\.]*)+)*)' // unix path
+ '(\?[^\s=&]+=[^\s=&]+(&[^\s=&]+=[^\s=&]+)*)?' // request (GET) params
+ '(#[\w\d\-%+]+)?'; // bookmark
function DecorateURLs (
// can find hyper links like 'http://...' or 'ftp://..'
// as well as links without protocol, but start with 'www.'
const AText : string; // Input text to find hyper-links
AFlags : TDecorateURLsFlagSet //= [durlAddr, durlPath]
// Which part of hyper-links found must be included into visible
// part of URL, for example if [durlAddr] then hyper link
// 'http://anso.da.ru/index.htm' will be decorated as
// '<a href="http://anso.da.ru/index.htm">anso.da.ru</a>'
) : string;
// Returns input text with decorated hyper links
var
PrevPos : integer;
s, Proto, Addr, HRef : string;
begin
Result := '';
PrevPos := 1;
with TRegExpr.Create do try
Expression := URLTemplate;
if Exec (AText) then
REPEAT
s := '';
if AnsiCompareText (Match [1], 'www.') = 0 then begin
Proto := 'http://';
Addr := Match [1] + Match [3];
HRef := Proto + Match [0];
end
else begin
Proto := Match [1];
Addr := Match [3];
HRef := Match [0];
end;
if durlProto in AFlags
then s := s + Proto;
if durlAddr in AFlags
then s := s + Addr;
if durlPort in AFlags
then s := s + Match [5];
if durlPath in AFlags
then s := s + Match [6];
if durlParam in AFlags
then s := s + Match [9];
if durlBMark in AFlags
then s := s + Match [11];
Result := Result + Copy (AText, PrevPos,
MatchPos [0] - PrevPos) + '<a href="' + HRef + '">' + s + '</a>';
PrevPos := MatchPos [0] + MatchLen [0];
UNTIL not ExecNext;
Result := Result + Copy (AText, PrevPos, MaxInt); // Tail
finally Free;
end;
end; { of function DecorateURLs }
//RegEx Online
const russTemplate = //'(?i)Ioeoeaeuiue eo?n OA ii aieea?o'
//'.*Aaoa\s*Eo?n\s*Eo?n iie.\s*Eo?n i?ia. [^<\d]*'
// '.*Äàòà\s*Êó?ñ\s*Êó?ñ ïîê.\s*Êó?ñ ï?îä.\s*Êóðñ íà?[^<\d]*'
'(\d?\d)/(\d?\d)/(\d\d)\s*[\d.]+\s*([\d.]+)';
procedure getREGEXOnline(Sender: TObject);
var http1: TIDHTTP;
htret: string;
begin
http1:= TIDHTTP.Create(self);
htret:= HTTP1.Get('http://win.www.citycat.ru/finance/finmarket/_CBR/');
//writeln(htret);
with TRegExpr.Create do try
Expression:= russTemplate;
if Exec(htret) then begin
//if
writeln(Format ('Russian rouble rate at %s.%s.%s: %s',
[Match[2], Match[1], Match[3], Match[4]]));
end;
//writeln(dump)
finally Free;
end;
//text2html
//writeln('deco: '+#13+#10+DecorateURLs(htret,[durlAddr, durlPath]))
end;
procedure ExtractPhones (const AText : string; APhones : TStrings);
begin
with TRegExpr.Create do try
Expression:= '(\+\d *)?(\((\d+)\) *)?(\d+(-\d*)*)';
if Exec (AText) then
REPEAT
if Match [3] = '812'
then APhones.Add (Match [4]);
UNTIL not ExecNext;
finally Free;
end;
end;
(*procedure regExGreedy;
var S, RE, Link, Text: string;
Match: TMatch;
begin
S := '<a href="go1.html">Go 1</a><a href="go2.html">Go 2</a>'; *)
//RE := '<a href="(.*)">(.*)</a>';
//Match:= TRegEx.Match(S, RE, [roIgnoreCase, roMultiLine, roCompiled]);
//while Match.Success do begin
//ShowMessage('URL: '+ Match.Groups[1].Value +', Text: ' + Match.Groups[2].Value);
//Match := Match.NextMatch;
//end;
//end;
procedure DelphiPerlRegex;
//var mot: TPerlRegExOptions;
begin
with TPerlRegex.create do try
Options:= Options + [preUnGreedy];
Subject:= 'I like to sing out at Foo bar';
RegEx:= '([1-9A-Za-z]+) bar';
//Study;
Replacement:= '\1 is the name of the bar I like';
if Match then ShowMessageBig(ComputeReplacement);
Subject:= 'This is a Linux or a Windows App.';
RegEx:= 'Windows|Linux'; // Matches 'Windows' or 'Linux', whichever comes first
if Match then showMessageBig(MatchedText +'came first!');
finally
Free;
end;
end;
//I have the following REGEX:
//^(\[[A-Za-z0-9,]+\])?([A-Za-z0-9]+:)?([A-Za-z]+)\(?([^\)]*)\)?$
(*When presented with Set(ID,99)
Perl returns:
1:[], 2:[], 3:[Set], 4:[ID,99] - as I expected
Delphi's Reg ex returns *)
procedure DelphiCoreCodeRegEx;
var regEx: TPerlRegEx;
i: integer;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
regEx:= TPerlRegEx.Create;
try
regEx.RegEx:= '^(\[[A-Za-z0-9,]+\])?([A-Za-z0-9]+:)?([A-Za-z]+)\(?([^\)]*)\)?$';
regEx.Subject:= 'Set(ID,99)';
WriteLn('Regex: '+regEx.RegEx);
WriteLn('Subject:'+regEx.Subject);
WriteLn('');
if regEx.Match then begin
for i:= 1 to 4 do
Write(Format('Group %d:[%s] ',[i,regEx.Groups[i]]));
end
else
WriteLn('Subject did not match the regular expression');
{ReadLn('')};WriteLn(' ');
finally
regEx.Free;
end;
except
//on E: Exception do
Writeln('E.ClassName'+ ': '+ E.Message);
end;
end;
var
parser: TPerlRegEx;
list: TStringList;
found: boolean;
it: integer;
const codestr1 ='2001, 2002, 200001, 2004, 1000000';
procedure DelphiCoreCodeRegEx2;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
list:= TStringList.Create;
try
parser:= TPerlRegEx.Create;
try
parser.RegEx:= '\b(\d{4})(?!\d)';
parser.Subject:= codeStr1;
found:= parser.Match;
while found do begin
list.Add(parser.Groups[1]);
found:= parser.MatchAgain;
end;
//for str in List do
//WriteLn('Matched: ',str);
for it:= 0 to list.count-1 do
WriteLn('Matched: '+list.strings[it]);
WriteLn('Total Matches: '+inttoStr(list.Count));
//ReadLn;
finally
parser.Free;
end;
finally
list.Free;
end;
except
//on E: Exception do
//Writeln(raiseLastException+ ' : '+ E.Message);
end;
end;
var PR: TPerlRegEx;
TestString: string;
procedure delphiRegexMailfinder;
begin
// Initialize a test string to include some email addresses. This would normally
// be your eMail text.
TestString:= '<one@server.domain.xy>, another@otherserver.xyz';
PR:= TPerlRegEx.Create;
try
PR.RegEx:= '\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b'; // <-- this is the actual regex used.
PR.Options:= PR.Options + [preCaseLess, premultiline];
PR.Compile;
PR.Subject:= TestString; // <-- tell the TPerlRegEx where to look for matches
if PR.Match then begin
// At this point a first matched eMail is already in MatchedText so grab it
WriteLn(PR.MatchedText); // Extract first address (one@server.domain.xy)
// Let the regex engine look for more matches in a loop:
while PR.MatchAgain do
WriteLn(PR.MatchedText); //Extract subsequent addresses(another@otherserver)
end;
finally PR.Free;
end;
//Readln;
end;
var
myf: extended;
secyear, lightyear: extended;//double;
regexres: TStrings;
gstr, fstr, email, rex, mystr, fs: string;
regEx, PR1: TPerlRegEx;
//myEval: TMatchEvaluator;
//match: TPerlMatch;
//main App of LED REGEX HEX BOX ****************************************
Begin
{fs:= 'northwest NW Charles Main 300000.00'#13#10+
'western WE Sharon Gray 53000.89'#13#10+
'southwest SW Lewis Dalsass 290000.73'+CR+LF+
'southern SO Suan Chin 54500.10'+CR+LF+
'southeast SE Patricia Hemenway 400000.00'+CR+LF+
'eastern EA TB Savage 440500.45'+CR+LF+
'northeast NE AM Main Jr. 57800.10'+CR+LF+
'north NO Ann Stephens 455000.50'+CR+LF+
'central CT KRush 575500.70'+CR+LF+
''+CR+LF+
'Extra [A-Z]****[0-9]..$5.00'; }
//SaveString(Exepath+'\examples\regexlist.txt',fs);
//memo2.text:= loadfileasString(Exepath+'\examples\regexlist.txt');
//SearchandOpenDoc(Exepath+'\examples\regexlist.txt');
//**************************** OOP in maXbox *******************************
//sizex, sizey as paras()
//pattern1:= '0123456789';
pattern1:= 'Pascal_Rex';
//pattern1:= 'THIS IS MAXLAND';
(*loadPForm(COL,ROW);
initPuzzle(COL);
InitLED_SignPatterns; VCLtester_VCLUtils*)
//ShowLED_TestSeq;
//WriteLed_Set('PASCAL')
//WriteLed_Set(pattern1)
//WriteLed_Set('MAXBOX')
//WriteLed_Set(pattern1, true) //true with animation
//Writeln(GetASCII)
writeln(floattostr(power(2,64)))
writeln('Formula Direct: '+floattoSTr(getFormulaValue('3*45+ln(34)-sqrt(16)')));
writeln('Formula Direct: '+floattoSTr(maxCalc('3*45+ln(34)-sqrt(16)')));
//writeln('Formula Direct: '+floattoSTr(maxCalc('20 mod 4'))); syntax error
//DomainCheck error
myf:= 123.059;
writeln('Formula ArcCos: '+floattoSTr(arccos(0.05998)));
writeln('Formula ArcSinH: '+floattoSTr(arcSinH(myf)));
PrintF('Formula Direct: %f ',[maxCalc('Ln(123.059+sqrt((123.059*123.059)+1))')]);
//Result := Ln(X + Sqrt((X * X) + 1));
SinCos(0, s1, c1); // 0 test
writeln('Formula SinCos: '+floattoSTr(s1)+ ' '+floattoSTr(c1));
s1:= 0.3; c1:= 0.5;
SinCos(1.0, s1, c1);
writeln('Formula SinCos: '+floattoSTr(s1)+ ' '+floattoSTr(c1));
SinCos(1.0, s1, c1);
// SinCosJ(1.0, s1, c1);
writeln('Formula SinCosJ: '+floattoSTr(s1)+ ' '+floattoSTr(c1));
//Ln((Sqrt(1 - X * X) + 1) / X)
writeln('PI is: '+floatToStr(PI)); //3.14159265358979
writeln('Formula Gauss first, s=3, z=0.0014: '+#13#10+
floattoSTr(maxCalc('1/sqrt(2*PI*3^2)')));
writeln('Formula Gauss second: '+
floattoSTr(maxCalc('exp((-0.0014^2)/(2*3^2))')));
// 8.68956546144783
writeln('Formula Gauss : '+
floatToSTr(maxCalc('1/SQRT(2*PI*3^2)*EXP((-0.0014^2)/(2*3^2))')));
//light seconds
printf('check of light year %f',[maxCalc('(60*24*60*365.25)*(299792458)')]);
//printf('check of lyear %f',[maxcalc('(60*24*60*365.25)*[metersperlightsecond]')]);
printf('this is ysec %d',[secondoftheyear(now)]);
printf('sec of year %f',[maxCalc('60*24*60*365.25')]);
//julian year
secyear:= (maxCalc('60*24*60*365.25'));
writeln('secyear: '+floattostr(secyear));
// 6149: GoldenMean: Float = 1.618033988749894848204586834365638; // GoldenMean
printf('golden mean %.18f',[goldenmean]);
printf('pi of j %.18f',[pij]);
printf('one parsec %.18f',[metersperparsec]);
printf('ref meters per light second %.18f',[metersperlightsecond]);
printf('ref meters per light year %.18f',[metersperlightyear]);
lightyear:= metersperlightyear;
//Result: 9.461 E12 kilometers
//one lightsecond (1 Ls) 299 792,458 km ~ 300 Millionen Meter ~ 300.000 km
//lightyear:= 9454254955E15;
writeln(floattostr(lightyear));
printf('meters per light sec2: %.12f',[lightyear / secyear]);
writeln(floattostr(lightyear/secyear));
printf('million of sec %f',[maXcalc('1E6 / (60*24*60)')]);
printf('2 ^64 -1 is 18 trillionen %.18f',[maXcalc('2^64-1')]);
printf('2 ^64 -1 is 18 trillionen %.21f',[power(2,64)-1]);
(*ShowmessageBig('this is the first HI on the line so the box goes LO on');
z:= $2345; // $2345 hex : $23 hi byte, $45 lo byte
ShowMessage(Format('Integer = $%x', [z]));
ShowMessage(Format('Hi byte = $%x', [Hi(z)]));
ShowMessage(Format('Lo byte = $%x', [Lo(z)]));*)
//printf('test million of sec %f',[lightyear * secyear]);
//************************************REGEX *****************************
// Function ExecRegExpr( const ARegExpr, AInputStr : RegExprString) : boolean');
///regex1 [12][09]\d{2}-\d{2}-\d{2}T12:[23]\d:\d{2}/
//regex2 result group = /((19)|(20))(\d{2}-\d{2}-\d{2}T)(12:[23]\d:\d{2})/
email:= 'max@kleiner.com';
rex:= '[\w\d\-\.]+@[\w\d\-]+(\.[\w\d\-]+)+';
writeln('email '+booleanToString(ExecRegExpr(rex, email)))
if ExecRegExpr (rex, email)
then writeln('gotcha! e-mail is valid ...') else writeln('email not valid');
if ExecRegExpr('((19)|(20))\d{2}-\d{2}-\d{2}T12:[23]\d:\d{2}',
'1925-04-01T12:23:29') then writeln('regex true') else writeln('regex false');
if ExecRegExpr('((19)|(20))(\d{2}-\d{2}-\d{2}T)(12:[23]\d:\d{2}-)',
'1925-04-01T12:23:29-') then writeln('regex true') else writeln('regex false');
//4464: Function RegExprSubExpressions(const ARegExpr: string; ASubExprs: TStrings; AExtendedSyntax : boolean) :
regexres:= TStringlist.Create;
RegExprSubExpressions('((19)|(20))(\d{2}-\d{2}-\d{2}T)(12:[23]\d:\d{2})',regexres,true);
writeln(regexres[4]);
//Procedure SplitRegExpr(const ARegExpr,AInputStr: RegExprString;APieces:TStrings)');
regexres.clear;
// java.util.regex.Matcher[pattern=((19)|(20))(\d{2}-\d{2}-\d{2}T)(12:[23]\d:\d{2}) region=0,19 lastmatch=] 12:33:29
SplitRegExpr('((19)|(20))(\d{2}-\d{2}-\d{2}T)(12:[23]\d:\d{2})',
'1925-04-01T12:233:29',regexres);
writeln(regexres[0]);
regexres.Free;
//last two müller - maierhuber are false
//[ae] a oder e //e? -> 0 oder 1 e
if ExecRegExpr('^M[ae][iy]e?r',
'"Meyer", "Meier", "Mair", "Mayer", "Maier", "Meir", "Müller", "Maierhuber"')
then writeln('regex maier true') else writeln('regex maier false');
if ExecRegExpr('M[ae][iy]e?r.*[be]', 'Mairhuberu')
then writeln('regex maierhuber true') else writeln('regex maierhuber false');
if ExecRegExpr('^[a-zA-Z_][a-zA-Z0-9_].*','pascal_name_kon')
then writeln('regex pascal true') else writeln('regex pascal false');
if ExecRegExpr('^[1-4]{3,}[A-D]{4,}$','121ABCD')
then writeln('regex hash true') else writeln('regex hash false');
//if ExecRegExpr('[1-9]{4,5}[A-F]{4,}','2127FADFF')
if ExecRegExpr('^([a-fA-F\d]{8})$','8a2127FA')
then writeln('regex hash true') else writeln('regex hash false');
//if ExecRegExpr('(?i)(?<![a-z0-9][a-f0-9]{32}?![a-z0-9])','8a2127FADFF')
//then writeln('regex hash true') else writeln('regex hash false');
if ExecRegExpr('^(:\d\d?\d?\d?\d?)$',':80009')
then writeln('regex port true') else writeln('regex port false');
//if ExecRegExpr('\b\d{4}(?!\d)',':80009')
//then writeln('regex lookahead true') else writeln('regex lookahead false');
//def myFile = new File("C:\\dateienmitback\\dateien\\sound\\aa_playlists\\songbird_20110301\\Rockdisco.m3u") //def group = "Queen"
regexres:= TStringlist.Create;
regexres.Clear;
//gstr:= 'The Doors';
//gstr:= 'Deep Purple';
fstr:= loadFileasString(Exepath+'examples\Rockdisco.m3u');
//writeln(fstr);
//SplitRegExpr('#EXTINF:\d{3},'+gstr+' - (.*)',fstr,regexres);
//writeln(regexres[0]);
//regexres.Free;
//with TRegExpr.Create do try
//modifiers:= /s;
//modifierG:= true;
// modifierS:= false;
// Expression:= '#EXTINF:\d{3},'+gstr+' - ([^\n].*)';
//Expression:= '#EXTINF:\d{3},The Doors - (.*)';
//if Exec(fstr) then begin
// writeln(Format ('Songs of Doors: %s', [Match[1]]));
//end;
//writeln(dump)
//((InvertCaseFunction
//finally Free;
//end;
with TRegExpr.Create do try
gstr:= 'Deep Purple';
modifierS:= false; //non greedy
//Expression := '(\+\d *)?(\((\d+)\) *)?(\d+(-\d*)*)';
Expression:= '#EXTINF:\d{3},'+gstr+' - ([^\n].*)';
if Exec(fstr) then
Repeat
//countmatch
writeln(Format ('Songs of ' +gstr+': %s', [Match[1]]));
{if AnsiCompareText(Match[1], 'Woman') > 0 then begin
closeMP3;
playMP3('D:\kleiner2005\ekon_11\EKON_13_14_15\EKON16\06_Woman_From_Tokyo.mp3');
end;}
Until Not ExecNext;
finally Free;
end;
regexres.Free;
// email:= 'max@kleiner.com';
rex:= '[\w\d\-\.]+@[\w\d\-]+(\.[\w\d\-]+)+';
fstr:= loadFileasString(Exepath+'examples\Simone_Seiler_Furrer.vcf');
with TRegExpr.Create do try
gstr:= 'simone';
modifierS:= false; //non greedy
//Expression := '(\+\d *)?(\((\d+)\) *)?(\d+(-\d*)*)';
Expression:= rex;
if Exec(fstr) then
Repeat
//countmatch
writeln(Format('mail of ' +gstr+': %s',[Match[1]]));
Until Not ExecNext;
finally Free;
end;
//regexres.Free;
//@Slide Examples EKON:
fstr:= '';
fstr:= loadfileasString(Exepath+'\examples\regexlist.txt');
with TRegExpr.Create do try
gstr:= 'perl';
modifierS:= false; //non greedy
//Expression := '(\+\d *)?(\((\d+)\) *)?(\d+(-\d*)*)';
Expression:= '(north[^\n].*)';
//Expression:= '\b\d{4}(?!\d)';
if Exec(fstr) then
Repeat
//countmatch
writeln(Format('match of ' +gstr+': %s',[Match[1]]));
Until Not ExecNext;
finally Free;
end;
//******************* compare perlregex - regexstudio *****************
//var mystr: string; Delphi RegEx - RegeX Studio
with TRegExpr.Create do try
//Make it case-insensitive
ModifierI:= True;
mystr:= '<body> My TRex on Regex</body>';
Expression := '<body.*>(.*?)</body>';
if Exec(Mystr) then
ShowMessageBig(Match[1]);
finally
Free;
end;
with TPerlRegEx.Create do try //Perl Delphi RegEx
RegEx:= '<title>(.+?)</title>';
Options:= [preCaseLess];
Subject:= 'testa <title> My TRex on Regex</title> testb';
//ResString:= Replace;
If Match then
ShowMessageBig(Groups[1]) //SubExpressions[1]) ,MatchedText
else
ShowMessageBig('Regex Not found');
finally
Free;
end;
//********* TMatchCollection EKON 16 Examples *****************************
//http://www.regexbuddy.com/delphi.html
fs:= 'Northwest NW Charles Main 300000.00'#13#10+
'Western WE Sharon Gray 53000.89'#13#10+
'southwest SW Lewis Dalsass 290000.73'+CR+LF+
'Southern SO Suan Chin 54500.10'+CR+LF+
'southeast SE Patricia Hemenway 400000.00'+CR+LF+
'eastern EA TB Savage 440500.45'+CR+LF+
'northeast NE AM Main Jr. 57800.10'+CR+LF+
'north NO Ann Stephens 455000.52'+CR+LF+
'ncentral CT KRush 575500.70'+CR+LF+
''+CR+LF+ //emptyline
//'Extra [A-Z]****[0-9]..$5.00'+CR+LF+
'Extra2 ^[A-Z]****[0-9]..$5.00'+CR+LF;
//rex:= '(north[^\n].*)';
//rex:= '.*NW|EA[^\n].*';
//rex:= '.*3+[^\n].*';
//rex:= '.*2\.?[0-9].*';
//rex:= '(no)+.*'; //Print all lines containing one or more consecutive occurrences of the pattern “no”.
//rex:= '.*S(h|u).*'; //Print all lines containing the uppercase letter “S”, followed by either “h” or “u”.
//rex:= '[A-Z]'+'****'+'[0-9]..$5.00';
//rex:= '^n.*';
//rex:= '.*\.00$';
//rex:= '.*5\..';
//rex:= '^[we].*';
//rex:= '.*\.[^0][^0].*'; //Print all lines ending with a period and exactly two non-zero numbers.
//rex:= '.*[0-9]{6}\..*'; //all lines at least 6 consecutive numbs follow. by a period.
//rex:= '\<north';
//rex:= '.*(es).*\1.*'; //subpattern
//rex:= '^No.*0$'; //subpattern
rex:= '^No.*0'; //greedy test
//rex:= '[]^[-]';
//rex:= '\b(\d{2,4})';
// rex:= '^[A-Z].*';
// rex:= '^.*$'; //emptyline
PR1:= TPerlRegEx.Create;
try
PR1.RegEx:= rex; //whole line!
Writeln('EKON 16 EXamples:');
//PR1.RegEx := '\b\d{4}(?!\d)';
PR1.Subject:= fs; //fstr;
//WriteLn('Regex: '+regEx.RegEx);
//WriteLn('Subject:'+regEx.Subject);
WriteLn('');
PR1.Options:= PR1.Options + [preCaseLess];
PR1.Options:= PR1.Options + [preMultiline];
//PR1.Options:= PR1.Options + [preUnGreedy];
//PR1.Compile;
if PR1.Match then begin
WriteLn('Firstmatch: '+PR1.MatchedText);
while PR1.MatchAgain do
WriteLn('Nextmatch: '+PR1.MatchedText); // Extract subsequent )
end;
{if regEx.Match then begin
for i:= 1 to 4 do
Write(Format('Group %d:[%s] ',[i,regEx.Groups[i]]));
end }
WriteLn(' ');
finally
PR1.Free;
end;
with TRegExpr.Create do begin
modifierS:= true; //greedy
ModifierI:= false;
ModifierM:= false;
end;
if ExecRegExpr(rex,fs)
then writeln('regex found') else writeln('regex not found');
//if ExecRegExpr('^[A-Z,a-z].*',fs)
//then writeln('regex found') else writeln('regex not found');
//getREGEXonLine(self);
DelphiPerlRegex;
DelphiCoreCodeRegEx;
DelphiCoreCodeRegEx2;
DelphiRegexMailfinder;
if ExecRegExpr('^[a-zA-Z_][a-zA-Z0-9_].*$','pascal_name_kon')
then writeln('regex pascal name true') else writeln('regex pascal name false');
Writeln(booleanToString(ExecRegExpr('^[a-zA-Z_][a-zA-Z0-9]*','pascal_name_kon')))
writeln('');
writeln('IP Test');
Writeln('IP Test '+booleanToString(ExecRegExpr('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}',
'192.168.1.044')))
Writeln('Tasche '+booleanToString(ExecRegExpr('T[ai]sche','Taaaasche')))
writeln('');
//writeln('deco: '+DecorateURLs('http://anso.da.ru/index.htm',[durlAddr]));
//oExpression:=TniRegularExpression.Create('PascalNames:[a-zA-Z_][a-zA-Z0-9_]*',[ ]);
//TniRegularExpressionMatchResult = (mrNone, mrFail, mrMatch, mrInsufficient);
//if oExpression.match('PascalNames:Get_function_A999') = mrMatch then
// writeln('expression matched! '+intToStr(oExpression.MatchCount)) else
// writeln('no matching');
//ShowMessage(ReplaceRegExpr('World','Hello, EKON World!', 'Earth',true));
//ShowMessageBig(ReplaceRegExpr('<.*?>','Dies ist ein <b>Text</b> mit <i>HTML</i>-Kennzeichen', '',true));
Writeln(ReplaceRegExpr('<.*?>','Dies ist ein <b>Text</b> mit <i>HTML</i>-Kennzeichen', '',true));
Writeln(ReplaceRegExpr('<.*>','Dies ist ein <b>Text</b> mit <i>HTML</i>-Kennzeichen', '',true));
Writeln(ReplaceRegExpr('<.>','Dies ist ein <b>Text</b> mit <i>HTML</i>-Kennzeichen', '',true));
//maxform1.SerialRS2321Click(self)
//Application.onmessage
//Application.onException
//label1click_EditPattern(self)
//DisplayStream
//SwapLong(swap_endian_u32)
// AESSymetricExecute(exepath+'examples\aestest.txt', exepath+'examples\aestest_encrypt/.txt','0001020304');
/// writeln('app handle '+ inttostr(application.handle));
//writeln('app owner'+ TApplication(application.owner).name);
// writeln('app name '+ (application.name));
End.
____ ___ _ ____ _ _ _
| _ \ | _| | | | _ \ | | | | | |
| | . | | |_ | | | |_| | | |_| | | |
| | | | | _| | | | __/ | _ | | |
| |_. | | |_ | |__ | | | | | | | |
|____/ |___| |____| |_| |_| |_| |_|
http://regexpstudio.com/tregexpr/help/whats_new.html
Ein Lichtjahr ist die Strecke, die eine elektromagnetische Welle wie das Licht in einem julianischen Jahr in absolutem Vakuum zurücklegt. Das sind etwa 9,5 Billionen Kilometer (9,5 · 1012 km).
Das Formelzeichen c (von lateinisch celeritas, Schnelligkeit) wird in vielen Fällen auch für die abweichende Ausbreitungsgeschwindigkeit in
1 Lj = 9 460 730 472 580 800 m
printf('check of light year %f',[maxcalc('(60*24*60*365.25)*(299792458)')]);
Für andere Jahresdefinitionen ergeben sich:
9.454.254.955.488.000 m bezüglich des Gemeinjahrs (exakt),
9.460.528.191.000.000 m bezüglich des tropischen Jahrs (zur Epoche J2000.0),
9.460.536.207.068.016 m bezüglich des gregorianischen Jahrs (exakt),
9.460.895.221.000.000 m bezüglich des siderischen Jahrs (zur Epoche J2000.0).
CL.AddConstantN('MetersPerLightYear','Extended').setExtended( MetersPerLightSecond * 31556925.9747); //mit 365.2422 !
RegEx for a valid file name: (?i)^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\\\./:\*\?\"<>\|][^\\/:\*\?\"<>\|]{0,254}$
Weiterführung der Scholz Software Systems 3S
The Jedi project provides the following solution in JclMath:
procedure SinCos(X: Float; var Sin, Cos: Float);
{$IFDEF CPU386}
procedure FSinCos(X: Float; var Sin, Cos: Float); assembler;
asm
FLD X
FSINCOS
FSTP Float PTR [EDX]
FSTP Float PTR [EAX]
FWAIT
end;
{$ENDIF CPU386}
begin
DomainCheck(Abs(X) > MaxAngle);
{$IFDEF CLR}
Sin := System.Math.Sin(X);
Cos := System.Math.Cos(X);
{$ELSE}
FSinCos(X, Sin, Cos);
{$ENDIF CLR}
end;
The domain check raises a exception in case of argument out of +2^63.
http://regexpstudio.com/tregexpr/help/whats_new.html
Text processing from bird's eye view
Do You want to write program for extracting weather forecast or currency rates or e-mails or whatsoever You want from HTML-pages, e-mails or other unformatted source? Or do You need to import data into Your database from old DB's ugly export form
There are two ways.
The traditional one - You must make full featured text parser. This is an awful peace of work!
For example, try to implement rules how to recognize e-mail address - simple code like
p := Pos ('@', email);
if (p > 1) and (p < length (email))
then ...
don't filter many common errors, for example, users frequently forget enter domain-part of e-mail, You'll need much more complex code (just read the big article "Extended E-mail Address Verification and Correction" on www.Delphi3000.com). Just th
The second way - look at the text from bird's eye view with help of regular expressions engine. You don't write the check processing routine, You just describe how regexp engine must do it for You. Your application will be implemented very fast a
Unfortunately, Delphi component palette contains no TRegularExpression component. But there are some third-party implementations (I think You already know at least one 8-)).
Example 1
How to chech e-mail address syntax.
Just write
if ExecRegExpr ('[\w\d\-\.]+@[\w\d\-]+(\.[\w\d\-]+)+', email)
then ... gotcha! e-mail is valid ...
Do not forget to add TRegExpr into uses section of the unit.
Example 2
How to extract phone numbers from unformatted text (web-pages, e-mails, etc).
For example, we need only St-Petersburg (Russia) phones (city code 812).
procedure ExtractPhones (const AText : string; APhones : TStrings);
begin
with TRegExpr.Create do try
Expression := '(\+\d *)?(\((\d+)\) *)?(\d+(-\d*)*)';
if Exec (AText) then
REPEAT
if Match [3] = '812'
then APhones.Add (Match [4])
UNTIL not ExecNext;
finally Free;
end;
end;
For the input text
"Hi !
Please call me at work (812)123-4567 or at home +7 (812) 12-345-67
truly yours .."
this procedure returns
APhones[0]='123-4567'
APhones[1]='12-345-67'
Example 3
Extracting currency rate from Russian Bank web page.
Create new project and place at the main form TBitBtn, TLabel and TNMHTTP components.
Add following code as BitBtn1 OnClick event handler (don't mind Russian letter - they need for Russian web-page parsing):
procedure TForm1.BitBtn1Click(Sender: TObject);
const
Template = '(?i)Ioeoeaeuiue eo?n OA ii aieea?o'
+ '.*Aaoa\s*Eo?n\s*Eo?n iie.\s*Eo?n i?ia. [^<\d]*'
+ '(\d?\d)/(\d?\d)/(\d\d)\s*[\d.]+\s*([\d.]+)';
begin
NMHTTP1.Get ('http://win.www.citycat.ru/finance/finmarket/_CBR/');
with TRegExpr.Create do try
Expression := Template;
if Exec (NMHTTP1.Body) then begin
Label1.Caption := Format ('Russian rouble rate %s.%s.%s: %s',
[Match [2], Match [1], Match [3], Match [4]]);
end;
finally Free;
end;
end;
5. time of day: For example. 11:30. [01][0-9]:[0-5][0-9] won't work well, because it would allow such impossible times as 19:00 and 00:30. A more complicated construction works better: (1[012] | [1-9]) :[0-5][0-9]. That is, a 1 followed by 0, 1, or 2, OR any digit 1-9.
procedure perlregex;
var mot: TPerlRegExOptions;
begin
with TPerlRegex.create do try
Options:= Options + [preUnGreedy];
Subject:= 'I like to sing out at Foo bar';
RegEx:= '([A-Za-z]+) bar';
Replacement:= '\1 is the name of the bar I like';
if Match then ShowMessageBig(ComputeReplacement);
Subject := 'This is a Linux or a Windows App.';
RegEx:= 'Windows|Linux'; // Matches 'Windows' or 'Linux', whichever comes first
if Match then showMessageBig(MatchedText +'came first!');
finally
free;
end;
end;
procedure PerlRegex;
var mot: TPerlRegExOptions;
begin
with TPerlRegex.create do
try
Subject:= 'I like to hang out at Foo bar';
RegEx:= '([A-Za-z]+) bar';
Replacement:= '\1 is the name of the bar I like';
if Match then ShowMessage(ComputeReplacement);
Subject := 'This is a Linux or a Windows App.';
RegEx := 'Windows|Linux'; // Matches 'Windows' or 'Linux', whichever comes first
if Match then showMessage(MatchedText + ' came first!');
finally
free;
end;
end;
------------------------Description
Match option enumeration set for the Perl regular expression.
Option Meaning
preCaseLess
Tries to match the regex without paying attention to case. If set, 'Bye' will match 'Bye', 'bye', 'BYE' and even 'byE', 'bYe', and so on. Otherwise, only 'Bye' will be matched. Equivalent to Perl's /i modifier.
preMultiLine
The ^ (beginning of string) and $ (ending of string) regex operators will also match right after and right before a new line in the Subject string. This effectively treats one string with multiple lines as multiple strings. Equivalent to Perl's /m modifier.
preSingleLine
Normally, dot (.) matches anything but a new line (\n). With preSingleLine, dot (.) will match anything, including new lines. This allows a multiline string to be regarded as a single entity. Equivalent to Perl's /s modifier. Note that preMultiLine and preSingleLine can be used together.
preExtended
Allow the regular expression to contain extra white spaces, new lines, and Perl-style comments, all of which will be filtered out. This is sometimes called "free-spacing mode".
preAnchored
Allows the regular expression to match only at the start of the subject or right after the previous match.
preUnGreedy
Repeat operators (?, *, +, {num,num}) are greedy by default, for example, they try to match as many characters as possible. Set preUnGreedy to use ungreedy repeat operators by default, for example, so that they try to match as few characters as possible.
preNoAutoCapture
Allows the regular expression to capture only named groups. Note that (group) is a non-capturing group.
It's unlikely that Emb will change this before XE3 because it would
require an interface change, however you can work around it like this :
uses
RegularExpressionsCore,
RegularExpressions;
type
TRegExCrack = record
private
FOptions: TRegExOptions;
FMatchEvaluator: TMatchEvaluator;
FNotifier: IInterface;
FRegEx: TPerlRegEx;
end;
//Note the above should match the layout of TRegEx exactly.
procedure dosomething;
var
regx : TRegEx;
begin
regx := TRegEx.Create('.*');
TRegEx2(regx).FRegEx.Options := TRegEx2(regx).FRegEx.Options +
[preUnGreedy];
.....
end;
The regular expression engine in Delphi XE is PCRE (Perl Compatible Regular Expression). It's a fast and compliant (with generally accepted regex syntax) engine which has been around for many years. Users of earlier versions of delphi can use it with TPerlRegEx, a delphi class wrapper around it.
The XE interface to pcre is a layer of units based on contributions from various people, the pcre api header translations in RegularExpressionsAPI.pas (Florent Ouchet and co), the wrapper class TPerlRegEx (Jan Goyvaerts) in RegularExpressionsCore.pas and the record wrappers on RegularExpressions.pas (myself). This unit is based on code we currently use in FinalBuilder 6 & 7, it's well tested and has proven to be very reliable in our products.
RegularExpressions.pas is what you will use in your code. It's loosely based on the .net regex interfaces.
The main type in RegularExpressions.pas is TRegEx. TRegEx is a record with a bunch of methods and static class methods for matching with regular expressions. The static versions of the methods are provided for convenience, and should only be used for one off matches, if you are matching in a loop or repeating the same search often then you should create an 'instance' of the TRegEx record and use the non static methods.
You will notice I don't free any of the TRegEx, TMatch or TGroups, that's because they are Records with methods rather than classes. This keeps memory management simple and helps avoid memory leaks, my original code used interfaces and reference counting but Embarcadero preferred to use records (as they have done with other new stuff introduced in recent releases).
Re: REGEX Delphi XE2 Question?
Click to report abuse... Click to reply to this thread Reply
Posted: Jul 20, 2012 6:41 AM in response to: Christopher Burke in response to: Christopher Burke
The only big difference is that I'm using the class method:
G:=TRegex.Match(...) I also tried G:=TRegex.Split as well.
Will try creating and using that instead.
This is the first time I've used the unit, and all defaults are as
installed.
I hope it helps! I've always used the RegularExpressionsCore unit rather
than the higher level stuff because the core unit is compatible with the
unit that Jan Goyvaerts has provided for free for years. That was my
introduction to regular expressions. So I forgot about the other unit. I
guess there's either a bug or it just doesn't work the way one might expect.
Personally, I don't think the low level code is too hard to work with, so
give it a try ans see if it works better for you.
Lee
northwest NW Charles Main 300000.00
western WE Sharon Gray 53000.89
southwest SW Lewis Dalsass 290000.73
southern SO Suan Chin 54500.10
southeast SE Patricia Hemenway 400000.00
eastern EA TB Savage 440500.45
northeast NE AM Main Jr. 57800.10
north NO Ann Stephens 455000.50
central CT KRush 575500.70
Extra [A-Z]****[0-9]..$5.00
bug comment on regex static record
procedure TForm1.Button1Click(Sender: TObject);
var
RegEx: TRegEx;
Match: TMatch;
begin
RegEx := TRegex.Create('\w+');
Match := RegEx.Match('One two three four');
while Match.Success do begin
Memo1.Lines.Add(Match.Value);
Match := Match.NextMatch;
end
end;
Or you could save yourself two lines of code by using the static TRegEx.Match call:
procedure TForm1.Button2Click(Sender: TObject);
var
Match: TMatch;
begin
Match := TRegEx.Match('One two three four', '\w+');
while Match.Success do begin
Memo1.Lines.Add(Match.Value);
Match := Match.NextMatch;
end
end;
Unfortunately, due to a bug in the RegularExpressions unit, the static call doesn’t work. Depending on your exact code, you may get fewer matches than you should, or you may get blank matches, or your application may crash with an access violation.
The RegularExpressions unit defines TRegEx and TMatch as records. That way you don’t have to explicitly create and destroy them. Internally, TRegEx uses TPerlRegEx to do the heavy lifting. TPerlRegEx is a class that needs to be created and destroyed like any other class. If you look at the TRegEx source code, you’ll notice that it uses an interface to destroy the TPerlRegEx instance when TRegEx goes out of scope. Interfaces are reference counted in Delphi, making them usable for automatic memory management.
The bug is that TMatch and TGroupCollection also need the TPerlRegEx instance to do their work. TRegEx passes its TPerlRegEx instance to TMatch and TGroupCollection, but it does not pass the instance of the interface that is responsible for destroying TPerlRegEx.
This is not a problem in our first code sample. TRegEx stays in scope until we’re done with TMatch. The interface is destroyed when Button1Click exits.
In the second code sample, the static TRegEx.Match call creates a local variable of type TRegEx. This local variable goes out of scope when TRegEx.Match returns. Thus the reference count on the interface reaches zero and TPerlRegEx is destroyed when TRegEx.Match returns. When we call MatchAgain the TMatch record tries to use a TPerlRegEx instance that has already been destroyed.
To fix this bug, delete or rename the two RegularExpressions.dcu files and copy RegularExpressions.pas into your source code folder. Make these changes to both the TMatch and TGroupCollection records in this unit:
Declare FNotifier: IInterface; in the private section.
Add the parameter ANotifier: IInterface; to the Create constructor.
Assign FNotifier := ANotifier; in the constructor’s implementation.
You also need to add the ANotifier: IInterface; parameter to the TMatchCollection.Create constructor.
Now try to compile some code that uses the RegularExpressions unit. The compiler will flag all calls to TMatch.Create, TGroupCollection.Create and TMatchCollection.Create. Fix them by adding the ANotifier or FNotifier parameter, depending on whether ARegEx or FRegEx is being passed.
With these fixes, the TPerlRegEx instance won’t be destroyed until the last TRegEx, TMatch, or TGroupCollection that uses it goes out of scope or is used with a different regular expression.
MatchedLength
Try the following expression RegEx := '\b\d{4}(?!\d)'
Breaking it down:
\b - Anchor: Match at word boundaries
\d - Character Class: digits (0-9)
{4} - Quantifier: Exactly 4
(?!\d) - Negative lookahead assertion. Match only if no digits follow
the preceding pattern sought.
For new code written in Delphi XE, you should definitely use the RegularExpressions unit that is part of Delphi rather than one of the many 3rd party units that may be available. If you're dealing with UTF-8 data, use the RegularExpressionsCore unit to avoid needless UTF-8 to UTF-16 to UTF-8 conversions.
myform
Genug Theorie. Wollen wir das mal an einem Beispiel anschauen:
$variable =~ m/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
Dieses Beispiel überprüft, ob $variable vier Zahlenblöcke mit ein bis drei Stellen enthält, getrennt durch einen Punkt (z.B. IP-Adresse). Hier sieht man: ein Punkt muss als \. geschrieben, da der Punkt alleine ein beliebiges Zeichen darstellt.
$variable =~ m/^[abc]/i;
Dieses Suchpattern ist wahr, wenn $variable mit a, b, c, A, B oder C anfängt.
$variable =~ m/(foo|bar)/;
In diesem Beispiel bezieht sich das Suchpattern nicht nur auf einzelne Zeichen (wie im oberen Beispiel mit [abc]) sondern auf ganze Wörter: die Bedingung ist in diesem Fall wahr, wenn $variable das Wort "foo" und/oder "bar" enthält (an beliebiger Stelle).
$variable =~ m/\.jpe?g$/;
Hier wird überprüft, ob $variable mit dem Text ".jpg" oder ".jpeg" endet (jedoch NICHT ".JPG"!).
$variable =~ m/^[a-z0-9\-_\.]+\@[a-z0-9\-_\.]+\.[a-z]{2,}$/i;
Hierbei handelt es sich um einen primitiven Check, ob $variable eine gültige Mailadresse enthält. In der Praxis müsste dies noch etwas erweitert werden (z.B. Domainnames mit Umlauten).