› Clovertech Forums › Read Only Archives › Cloverleaf › Cloverleaf › regular expression issue w/ TCL
I can not get certain regular expressions to evaluate properly in my TCL script. I am trying to ensure that a variable starts with 12 numbers.
echo [regexp {[^d{12}]} $obx14] <-- should eval to "true" if $obx14 starts wtih 12 numbers
Have also tried these equivalent statements…
^dddddddddddd
^[0-9]{12}
All should return true only if the string begins with 12 numbers. I’ve tested all of these in other environments and they work properly. However, all will incorrectly evaluate to “true” for empty strings or for strings of numbers < 12 in TCL. See below:
1 = true
1a = false
1111 = true
a = false
Any ideas?
Close but no cigar 😀
Just take it out of the brackets which means match anyone of the chars within the brackets.
echo [regexp — {^d{12}} $obx14]
Of course you could od something like:
echo [regexp {[^d]{12}} $obx14]
But why?
The square brackets mean a range of characters or a set of characters like [0-9] or [a-b]. d is equivalent to [0-9].
{^d{12}} is the same as {^[0-9]{12}.
You can have more than one range in the square brackets like {[a-bA-B].}
Here’s an example set: {[abc123]}. That would match on a, b, c, 1, 2, or 3.
-- Max Drown (Infor)
I think that it should be this way
regexp {^[d]{12}} $obx14
carrot inside square brases states anything but 12 digits
tcl>set obx14 12345678901a12
12345678901a12
tcl>regexp {^[d]{12}} $obx14
0
tcl>set obx14 a1234567890123
a1234567890123
tcl>!re
regexp {^[d]{12}} $obx14
0
tcl>set obx14 1234567890123asc
1234567890123asc
tcl>!re
regexp {^[d]{12}} $obx14
1
Regards,
Alex
Charlie,
echo [regexp — {^d{12}} $obx14] works great!
Thanks much, guys!
I think that it should be this way
regexp {^[d]{12}} $obx14
The square braces around the d are not needed. It would work, but not needed.
-- Max Drown (Infor)
Instead of the 12 digit limitation, how would you do regexp {^d} $num where the num can end up being any digit greater than 0?
regexp {^[1-9]} $obx14
-- Max Drown (Infor)
but that won’t take into account 10 or 100 or 1000.
Oh, I wouldn’t use regexp for that. Instead do something like “if {$var > 100}”. You can use regexp to capture the number if needed.
-- Max Drown (Infor)
Or you could modify Max’s regexp like:
regexp {^[1-9]d*} $obx14
This will be true for any number that starts with 1-9 followed by 0 or more numbers after. If the number following the 1-9 can only be 0, try:
regexp {^[1-9]0*} $obx14
Or as Max just said, if you are looking to see that a number larger than or 10 or 100, or whatever exists, simply do an if statement
You never did state the purpose of this.
Well I didn’t want to use if ($var > 0 ) because I am actually searching a file for a string that matches “150 Opening data connection for PATHTRNS (39123 bytes).” but where the filename, in this case “PATHTRNS”, and the file size can vary; however, if the file size is “0”, that’s an entirely different branch on my if/elseif/else statement.
I like [1-9]d* — it’s much simpler and easier to read than my [1-9][0-9]*?
Regexp seems like something very cool and “neat” like dating and politics until you actually try it and spend four days banging your head against a brick wall because you can’t figure out why it doesn’t work the way you think it should.
What is the set of possible matches you are looking for? You have 150 in the example, but what could the other valid values be? What would an invalid value be?
-- Max Drown (Infor)
SUCCESSFUL FILE
150 Opening data connection for $fileName ($fileSize bytes).
EMPTY FILE
150 Opening data connection for $fileName (0 bytes).
MISSING FILE
550 $fileName: A file or directory in the path name does not exist.
I’ve read your posts a couple of times, but I’m still not sure exactly what you need the regexp to do.
-- Max Drown (Infor)
O.K.
Our Cloverleaf server picks up and processes batch billing files for 5 or 6 applications/departments and the resulting charge files are placed in a folder called “BILLING”. Currently, the mainframe-based finance application that does the actual billing picks up those files in the evening but it doesn’t delete them nor do we receive an email of any sort to indicate that the files have been successfully picked up by that application — when the “end users” don’t get their daily billing reports, the first people that are contacted are the billing people who insist they know nothing and the application folks always insist that everything worked on their side, which is why we currently have emails and daily reports which indicate what was successful and what wasn’t. Of course, there is no way to prove that the billing application picked up the files or didn’t.
So, we finally convinced them to start sending us “something” which turns out to be one text file for each charge file which contains the ftp responses when the billing application attempted to grab the charge file. Now, all I have to do is read that file into a list (each line is an element); then I have to step through that list and check for one of those three magic strings so I can then send an email and possibly multiple pages as needed.
Hopefully that explains better what I’m attempting to do.
The magic strings are lines in the file? Can you paste the lines both valid and invalid?
-- Max Drown (Infor)
As above, a sample file would be:
EZA1736I FTP
EZY2640I Using /etc/ftp.data for local site configuration parameters.
EZA1450I IBM FTP CS V1R10
EZA1466I FTP: using TCPIP
EZA1456I Connect to ?
EZA1736I xxx.xx.xx.xx (EXIT
EZA1554I Connecting to: xxx.xx.xx.xx port: 21.
220 bmc_p550_01 FTP server (Version 4.2 Fri May 2 12:48:10 CDT 2008) ready.
EZA1459I NAME (xxx.xx.xx.xx:TXDME):
EZA1701I >>> USER BILLING
331 Password required for BILLING.
EZA1701I >>> PASS
230-Last unsuccessful login: Tue Mar 24 07:07:47 EDT 2009 on ftp from xxx.xx.xx.xx
230-Last login: Wed Apr 14 20:00:13 EDT 2010 on ftp from ::ffff:xxx.xx.xx.xx
230 User BILLING logged in.
EZA1460I Command:
EZA1736I GET CARDTRNS //DD:TRANSIN (REPLACE
EZA1701I >>> PORT xxx,xx,x,xx,xxx,xxx
200 PORT command successful.
EZA1701I >>> RETR CARDTRNS
550 CARDTRNS: A file or directory in the path name does not exist.
EZA1735I Std Return Code = 16550, Error Code = 00002
EZA1701I >>> QUIT
221 Goodbye.
I am looking for one of three possible lines — depending on the name of the file; for example, in this case the name of this file would have told me to look for CARDTRNS as the file the ftp was attempting to pick up. So $fileName = CARDTRNS.
Unfortunately, this script will not know the correct file size in bytes so this is my [1-9][0-9]*? because it can be any number greater than 0 if the file was successfully picked up.
SUCCESSFUL FILE
150 Opening data connection for $fileName ($fileSize bytes).
EMPTY FILE
150 Opening data connection for $fileName (0 bytes).
MISSING FILE
550 $fileName: A file or directory in the path name does not exist.
Are you trying to do something like this?
foreach line [split $filecontents n] {
if { [regexp {150 Opening data connection for (.*) (0 bytes).} $line -> filename] } {
echo do something for empty file $filename
} elseif {[regexp {550 (.*): A file or directory in the path name does not exist.} $line -> filename] } {
echo do something for bad transfer of $filename
} elseif { [regexp {150 Opening data connection for (.*) ((d+) bytes).} $line -> filename filesize] } {
echo do something for good transfer of $filename with size $filesize
}
}
I had the hardest time with this. For some reason I could not get {} around the regular expression to work. I grep’d our tclproc dir and discovered that we have no examples of an if…regexp with braces around the regular expression.
The literal parenthesis () around the “0 bytes” was what was causing all of my problems apparently. I finally figured out what I had to put there:
foreach line [split $msg “n”] {
# Check for No File Found
if { [ regexp “^550 $billFile: A file or directory in the path name does not exist.$” $line ] } {
#Process no File
break
# Check for empty file found —
} elseif { [ regexp “^150 Opening data connection for $billFile \((0 bytes\)).” $line ] } {
#Process empty File
break
# If it’s not empty, it’s a Success!!!!
} elseif { [ regexp “^150 Opening data connection for $billFile \(([1-9][0-9]*? bytes\)).” $line ] } {
#Process successfully collected File
break
} else {
#do nothing
}
}
See this ridiculousness —
\(([1-9][0-9]*? bytes\)).
?
The first two forward slashes make one literal slash “” so that the next parenthesis will be read as a literal parenthesis “(” by the regexp; the next parenthesis is actually the beginning of a grouping parenthesis apparently. The confusing bits were the “\((” and “\))”. It never occurred to me that the parenthesis were being read in that way.
Normally it’s best to use squirrelies ({}) instead of quotes around regular expressions.
Maybe I am missing something but it seems to me you rae making this overly complex.
If there were an error fetching the file, I asume you will only have one line, the error message? Why not simply put this code before the loop
switch -regexp — $msg {
^550 {
Handle 550 error
}
^150 {
if {[regexp — {0 bytes} $msg]]} {
Handle empty file
} else {
Handle error
}
}
}
IF you get to here it is a good file then you can fo the loop
Well, part of the trick was to verify that it was in fact the correct file that was being picked up, which is why I had $billFile in the regexp. To use your regexp, I would have to have a second regexp to verify that that the $billFile name is in that string/line after verifying that statement was in the file of ftp results codes.
I wouldn’t want to assume that just because the file the Medipac script produces is called IMP_Results.txt that it really did pick up IMPCTRNS. It’s better to check every little thing and make certain that our side is blunder-proof.