[...]
Ping Janis: Question... Are you interested in rewriting this
as a Gawk only implementation? Would be great for switch/case
statements IMO. If so, I'll add your version to the file at
my website.
Folks, assuming Janis says yes, lets work off that version
& use it as a baseline.
At any rate, a work in progress...
[...]
{ RPN($0) }
function RPN(input, x, y, z, stack) {
split(input, stack, /[[:space:]]+/)
z = 0
for (x = 1; x in stack; ++x) {
y = stack[x]
if (y ~ /^[0-9]+(\.[0-9]+)?$/) stack[++z] = y
else {
if (z < 2) { print "error: insufficient operands"; return }
if (y == "+") stack[z-1] += stack[z]
else if (y == "-") stack[z-1] -= stack[z]
else if (y == "*") stack[z-1] *= stack[z]
else if (y == "^") stack[z-1] ^= stack[z] # see footnotes
else if (y == "/") {
if (stack[z] == 0) { print "error: division by zero"; return }
stack[z-1] /= stack[z]
} else if (y == "%") {
if (stack[z] == 0) { print "error: modulo by zero"; return }
stack[z-1] %= stack[z]
} else { print "error: invalid operator " y; return }
--z
}
}
if (z != 1) { print "error: invalid RPN expression"; return }
printf "%0.2f\n", stack[z]
}
[...]
the switch statement (for simple string comparisons) looks like
switch (some_variable) {
case "Val1": Cmd1 ; break ;
case "Val2": Cmd2 ; break ;
...
default: Def ;
}
I don't see any GNU Awk specific features/constructs that would
suggest a [non-portable] transcription.
(but test that in your Awk versions before using it; "&" is an
old feature but off the top of my head I'm not sure whether the
subexpression with parenthesis /...(...).../ is generally
supported in other Awks).
On 06.11.2023 03:26, Mike Sanders wrote:Nitpick - it's
Ping Janis: Question... Are you interested in rewriting this
as a Gawk only implementation? Would be great for switch/case
statements IMO. If so, I'll add your version to the file at
my website.
This is no rocket science. If you have
if (some_variable = "Val1") Cmd1 ;
else if (some_variable = "Val2") Cmd2 ;
...
else Def ;
the switch statement (for simple string comparisons) looks like
switch (some_variable) {
case "Val1": Cmd1 ; break ;
case "Val2": Cmd2 ; break ;
...
default: Def ;
}
The point is that you have to provide and evaluate 'some_variable'
just once. The "disadvantage" is that you will need the 'break'
commands to not fall through to the next case (which is another
common feature of such statements but not necessary in your
case).
You can apply 'switch' in function RPN() and errormessage(), but
whether it makes sense or not to introduce 'switch' and sacrifice portability is on you to decide.
GNU Awk has (as opposed to some other programming languages
like C) the advantage that you can compare not only scalars;
you can also compare strings and patterns in GNU Awk's switch:
switch (some_variable) [
case 42: ...
case "string": ...
case /pattern/: ...
}
I don't see any GNU Awk specific features/constructs that would
suggest a [non-portable] transcription.
One point you may want to consider is the trim() function; theYou can write that, but it's not a capture group that can be
two substitutions can be combined in one
sub (/^[[:space:]]+(.*)[[:space:]]+$/, "&", str)
(but test that in your Awk versions before using it; "&" is an
old feature but off the top of my head I'm not sure whether the subexpression with parenthesis /...(...).../ is generally
supported in other Awks).
Janis
Folks, assuming Janis says yes, lets work off that version
& use it as a baseline.
At any rate, a work in progress...
[...]
{ RPN($0) }
function RPN(input, x, y, z, stack) {
split(input, stack, /[[:space:]]+/)
z = 0
for (x = 1; x in stack; ++x) {
y = stack[x]
if (y ~ /^[0-9]+(\.[0-9]+)?$/) stack[++z] = y
else {
if (z < 2) { print "error: insufficient operands"; return }
if (y == "+") stack[z-1] += stack[z]
else if (y == "-") stack[z-1] -= stack[z]
else if (y == "*") stack[z-1] *= stack[z]
else if (y == "^") stack[z-1] ^= stack[z] # see footnotes
else if (y == "/") {
if (stack[z] == 0) { print "error: division by zero"; return }
stack[z-1] /= stack[z]
} else if (y == "%") {
if (stack[z] == 0) { print "error: modulo by zero"; return }
stack[z-1] %= stack[z]
} else { print "error: invalid operator " y; return }
--z
}
}
if (z != 1) { print "error: invalid RPN expression"; return }
printf "%0.2f\n", stack[z]
}
[...]
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
the switch statement (for simple string comparisons) looks like
switch (some_variable) {
case "Val1": Cmd1 ; break ;
case "Val2": Cmd2 ; break ;
...
default: Def ;
}
Can multiple cases be 'or'ed (combined) as in $SHELL?
case q|Q) quit(); break;[...]
On 11/6/2023 5:14 AM, Janis Papanagnou wrote:
switch (some_variable) [
case 42: ...
case "string": ...
case /pattern/: ...
Nitpick - it's
case /regexp/:
rather than:
case /pattern/
The word "pattern" is ambiguous and misused all over awk documentation.
You can make some argument for it in:
pattern { action }
since that includes `BEGIN`, integers, etc. I'd argue that should be:
condition { action }
but in the "case" statement above what goes inside `/.../` is simply and always a regexp.
[...]
One point you may want to consider is the trim() function; the
two substitutions can be combined in one
sub (/^[[:space:]]+(.*)[[:space:]]+$/, "&", str)
(but test that in your Awk versions before using it; "&" is an
old feature but off the top of my head I'm not sure whether the
subexpression with parenthesis /...(...).../ is generally
supported in other Awks).
You can write that, but it's not a capture group that can be
backreferenced from the replacement and if it was "&" wouldn't refer to
the string that matched ".*" anyway, it'd refer to the string that
matched the whole regexp.
You could use a capture group in GNU awk for gensub():
str = gensub (/^[[:space:]]+(.*)[[:space:]]+$/, "\\1", 1, str)
and in most awks you could do:
gsub (/^[[:space:]]+|[[:space:]]+$/, "", str)
but there are some out there that will fail to do both substitutions for
that case (tawk and nawk maybe?) and so you need:
sub(/^[[:space:]]+/, "", str)
sub(/[[:space:]]+$/, "", str)
[...]
One point you may want to consider is the trim() function; the
two substitutions can be combined in one
sub (/^[[:space:]]+(.*)[[:space:]]+$/, "&", str)
(but test that in your Awk versions before using it; "&" is an
old feature but off the top of my head I'm not sure whether the
subexpression with parenthesis /...(...).../ is generally
supported in other Awks).
You can write that, but it's not a capture group that can be
backreferenced from the replacement and if it was "&" wouldn't refer to
the string that matched ".*" anyway, it'd refer to the string that
matched the whole regexp.
Using my Awk it does what advertised. I merely didn't find it clearly documented whether the '&' is generally guaranteed to refer to the
grouping.
Ping Janis: Question... Are you interested in rewriting this
as a Gawk only implementation? Would be great for switch/case
statements IMO. If so, I'll add your version to the file at
my website.
[*] https://www.gnu.org/software/gawk/manual/gawk.html#Switch-Statement
The cppawk preprocessor supports a case macro which
compiles to the switch statement for Gawk, or to portable
Awk code.
The macro is documented in its own man page:
https://www.kylheku.com/cgit/cppawk/tree/cppawk-case.1
case is safer than switch because it doesn't have implicit
"fallthrough".
Each case must end with one of: cbreak, cfall or cret: break,
fallthrough or return.
On 07.11.2023 12:48, Ed Morton wrote:<snip>
and in most awks you could do:
gsub (/^[[:space:]]+|[[:space:]]+$/, "", str)
Yes, this is a sensible alternative.
but there are some out there that will fail to do both substitutions for
that case (tawk and nawk maybe?) and so you need:
Really? But why? - Alternatives in regexp is certainly an old feature
(at least since nawk in the 1980's).
On 11/7/2023 7:02 AM, Janis Papanagnou wrote:
On 07.11.2023 12:48, Ed Morton wrote:<snip>
and in most awks you could do:
gsub (/^[[:space:]]+|[[:space:]]+$/, "", str)
Yes, this is a sensible alternative.
but there are some out there that will fail to do both substitutions for >>> that case (tawk and nawk maybe?) and so you need:
Really? But why? - Alternatives in regexp is certainly an old feature
(at least since nawk in the 1980's).
In my opinion it's just a bug. It was demonstrated to me when I posted
an answer on Stack Overflow several years ago that I can't find right
now. I know it's not gawk and I'm about 99% sure it's neither BSD awk
nor /usr/xpg[46]/bin/awk so the only non-oawk awks I can imagine would
have this problem are nawk, tawk (I'm about 80% sure I remember tawk is
one that DOES have the problem), and/or busybox awk, none of which I
have access to, so if anyone has and could test them by running:
$ echo ' foo ' | awk '{gsub(/^ +| +$/,""); print "<" $0 ">"}' <foo>
and let us know which don't produce that output, that'd be great.
Ed.
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,030 |
Nodes: | 10 (0 / 10) |
Uptime: | 201:18:51 |
Calls: | 13,340 |
Calls today: | 3 |
Files: | 186,574 |
D/L today: |
3,597 files (1,123M bytes) |
Messages: | 3,357,067 |