bc 计算器似乎为未初始化的变量分配零值。我想改变这种行为,以便当 bc 遇到未初始化的变量时,它会将表达式标记为无效。例如,在下面的代码中,
echo "foo + bar" | bc -l
bc 将值 0 赋给 foo 和 bar 并返回“0”。我希望它返回空字符串“”或以其他方式指示“foo + bar”是无效表达式。有没有办法在 bc 中实现这一目标?
答案1
为了回答我自己的问题,除了在 bc 中将未声明的变量标记为无效的方法之外,我想出了一个可行的解决方案,以防它对其他人有用。 bc 要执行的表达式首先通过 sed 命令进行管道传输,该命令会从表达式中删除任何保留的 bc 字。任何剩余的变量名都被认为是未声明的变量,并且整个表达式被转换为一个语句,该语句在 bc 中执行时将强制出现错误(我选择了“1/0”,但是可以构造许多替代错误标志中的任何一个) .)
生成运行时“除以零”错误:
echo 'foo + bar' | sed -E '
## Save the original expression in the hold space
h
## Recursively replace all bc reserved words with a unique token string (¦§§¦)
:again
s/auto|break|continue|define|else|for|halt|ibase|if|last|length|limits|obase|print|quit|read|return|scale|sqrt|warranty|while/¦§§¦/g
s/(a|c|e|j|l|s)([(][^)]*[)])/¦§§¦\2/g
t again
## If the expression contains any bc reserved words abutting one another, mark the expression as invalid, and skip to the end of the sed script
/¦§§¦¦§§¦/s/^.+$/1\/0/
t
## Replace all tokens with spaces
s/¦§§¦/ /g
## If any variable names remain, treat them as undeclared variables, mark the expression as invalid, and skip to the end of the sed script
## Prior to doing this, reset the t command so that it can recognize if a substitution takes place in the s command
t reset
:reset
/[a-z][a-z0-9_]*/s/^.+$/1\/0/
t
## If the expression does not have undeclared variable names, get the original expression from the hold space
g
' | bc -l
返回正确答案 = 246:
echo '123 + 123' | sed -E '
## Save the original expression in the hold space
h
## Recursively replace all bc reserved words with a unique token string (¦§§¦)
:again
s/auto|break|continue|define|else|for|halt|ibase|if|last|length|limits|obase|print|quit|read|return|scale|sqrt|warranty|while/¦§§¦/g
s/(a|c|e|j|l|s)([(][^)]*[)])/¦§§¦\2/g
t again
## If the expression contains any bc reserved words abutting one another, mark the expression as invalid, and skip to the end of the sed script
/¦§§¦¦§§¦/s/^.+$/1\/0/
t
## Replace all tokens with spaces
s/¦§§¦/ /g
## If any variable names remain, treat them as undeclared variables, mark the expression as invalid, and skip to the end of the sed script
## Prior to doing this, reset the t command so that it can recognize if a substitution takes place in the s command
t reset
:reset
/[a-z][a-z0-9_]*/s/^.+$/1\/0/
t
## If the expression does not have undeclared variable names, get the original expression from the hold space
g
' | bc -l
编辑说明:这是我原始提交的改进,在检测未声明的变量名称方面更加准确。
答案2
考虑使用expr
?
$ expr foo + bar
expr: non-integer argument
$ expr 1 + 5
6