|
|
 |
 |
 |
 |
TCL(Tool Command Language) Scripting
|
 |
 |
 |
 |
 |
 |
 |
 |
How to do a NOT in TCL?
Hi, I have a program that uses tcl7.5 regexp to find the following unix:.* (WARN|NOTICE) I would like to alter this to something like. unix:.* (WARN|NOTICE) && ![^core] I have been told that TCL cannot handle logical NOTs, but I thought I'd just check with the experts in this group for confirmation. I tested the second expression above using awk and of course it worked. I have also tried unix:.* (WARN|NOTICE).*[^core]{0} I'm not sure if I have the syntax correct above, but what I'm trying to say is look for unix: then any characters followed by a space, then EITHER WARN or NOTICE, then any characters, but only when there a '0' (zero) occurances of core. Hmm, hope someone understands what I'm trying to do. ;-) Cheers Craig.
On May 31, 5:12 pm, cabkiz_fam@hotmail.com wrote:
> Hi, > I have a program that uses tcl7.5 regexp to find the following > unix:.* (WARN|NOTICE) > I would like to alter this to something like. > unix:.* (WARN|NOTICE) && ![^core] > I have been told that TCL cannot handle logical NOTs, but I thought > I'd just > check with the experts in this group for confirmation. > I tested the second expression above using awk and of course it > worked. > I have also tried > unix:.* (WARN|NOTICE).*[^core]{0} > I'm not sure if I have the syntax correct above, but what I'm trying > to say is > look for unix: then any characters followed by a space, then EITHER > WARN or NOTICE, then > any characters, but only when there a '0' (zero) occurances of core. > Hmm, hope someone understands what I'm trying to do. ;-)
Logical not is not part of any standard regular expression notation. The regular languages are closed under complementation, which one can see by taking a deterministic machine and swapping the accepting and non-accepting states, but there isn't any straightforward corresponding regular expression notation. However, Tcl does support logical not at the expression level, so you can do things like: [regexp {unix:.* (WARN|NOTICE).*} $s] && ![regexp {unix:.* (WARN| NOTICE).*core} $s] where the first regular expression is more general and the second one matches a subset of the strings matched by the first. In the specific case you mention, though, a "regular expression" with a negative forward assertion will work: ^unix:.* (WARN|NOTICE(?!core)$ The part (?!core) blocks matches ending in "core".
On May 31, 5:12 pm, cabkiz_fam@hotmail.com wrote:
> Hi, > I have a program that uses tcl7.5 regexp to find the following > unix:.* (WARN|NOTICE) > I would like to alter this to something like. > unix:.* (WARN|NOTICE) && ![^core] > I have been told that TCL cannot handle logical NOTs, but I thought > I'd just > check with the experts in this group for confirmation. > I tested the second expression above using awk and of course it > worked. > I have also tried > unix:.* (WARN|NOTICE).*[^core]{0} > I'm not sure if I have the syntax correct above, but what I'm trying > to say is > look for unix: then any characters followed by a space, then EITHER > WARN or NOTICE, then > any characters, but only when there a '0' (zero) occurances of core. > Hmm, hope someone understands what I'm trying to do. ;-) > Cheers > Craig.
Oh, I should say that Tcl 7.5 is very old. I think that it probably doesn't support assertions since the new regular expression package came in with Tcl 8.0. Why on earth are you using such an ancient Tcl?
cabkiz_fam@hotmail.com schrieb: > Hi, > I have a program that uses tcl7.5 regexp to find the following > unix:.* (WARN|NOTICE)
If you wanted to match either WARN or NOTICE the expression ought to be ((WARN)|(NOTICE)). Otherwise the only thing it matches is WARNOTICE. > I would like to alter this to something like. > unix:.* (WARN|NOTICE) && ![^core]
I guess you do not mean "any character apart from c,e,o and r", right? Because that's what [^core] means in a regular expression. > I have been told that TCL cannot handle logical NOTs, but I thought > I'd just > check with the experts in this group for confirmation.
It can, just not in a single expression. You do if {[regexp {.* ((WARN)|(NOTICE))} $String] && ![regexp core $String]} { ... } > I tested the second expression above using awk and of course it > worked.
Not sure how you managed that. None of the expressions you posted worked for the grep on /my/ machine. > I have also tried > unix:.* (WARN|NOTICE).*[^core]{0} > I'm not sure if I have the syntax correct above, but what I'm trying > to say is > look for unix: then any characters followed by a space, then EITHER > WARN or NOTICE, then > any characters, but only when there a '0' (zero) occurances of core. > Hmm, hope someone understands what I'm trying to do. ;-)
Lots of Greetings! Volker -- For email replies, please substitute the obvious.
En Fri, 01 Jun 2007 18:27:43 +0200, Volker Hetzer <firstname.lastn@ieee.org> escribi: > (WARN|NOTICE) > I have a program that uses tcl7.5 regexp to find the following > unix:.* (WARN|NOTICE) > If you wanted to match either WARN or NOTICE the expression > ought to be ((WARN)|(NOTICE)). Otherwise the only thing it > matches is WARNOTICE.
Did you try it before answering? (Documents) 1 % regexp {^(WARN|NOTICE)$} NOTICE 1 (Documents) 2 % Ramon Rib
cabkiz_fam @hotmail.com wrote: > I have a program that uses tcl7.5 regexp to find the following > unix:.* (WARN|NOTICE) > I would like to alter this to something like. > unix:.* (WARN|NOTICE) && ![^core] > I have been told that TCL cannot handle logical NOTs, but I > thought I'd just > check with the experts in this group for confirmation. > I tested the second expression above using awk and of course it > worked. > I have also tried > unix:.* (WARN|NOTICE).*[^core]{0} > I'm not sure if I have the syntax correct above, but what I'm > trying to say is > look for unix: then any characters followed by a space, then > EITHER WARN or NOTICE, then > any characters, but only when there a '0' (zero) occurances of > core.
I assume you are updating an old script that used to run on Tcl7.5, but you will be using a more recent version of Tcl. In that case you may be able to use the negative lookahead feature for regular expressions. I have to admit I am usually surprised by the results when I try to use this feature, but I think for your case this should work: regexp {unix:.* (WARN|NOTICE)(?!.*core)} $str Schelte. -- set Reply-To [string map {nospam schelte} $header(From)]
cabkiz_fam @hotmail.com wrote: > I would like to alter this to something like. > unix:.* (WARN|NOTICE) && ![^core] > I have been told that TCL cannot handle logical NOTs, but I thought > I'd just check with the experts in this group for confirmation.
It doesn't handle logical negation, since that's a surprisingly non- trivial concept with REs for fairly deep reasons. However, it does provide some techniques that can help. Most important among these is the negative lookahead assertion, which is *almost* negation. But with some important restrictions, the most important of which are that they cannot have backreferences in (not that that matters this time) and that they are always non-greedy. They're also quite slow (though we mitigate that by putting them at the end of the RE). The RE you are looking for is probably something like this: unix:.*\m(WARN|NOTICE)\M(?!.*\mcore\M.*$).* You'll want to make sure you put that in {braces}, of course. (The \m and \M ensure that you don't get tripped up by words like "scores"...) Donal (alas, no time to explain properly what this does today...)
|
 |
 |
 |
 |
|