bc電卓が初期化されていない変数にゼロ値を割り当てるようです。 bcが初期化されていない変数を見つけた場合、式が無効とマークされるようにこの動作を変更したいと思います。たとえば、以下のコードでは
echo "foo + bar" | bc -l
bc は foo と bar に値 0 を割り当て、「0」を返します。空の文字列""を返すか、"foo + bar"が誤った式であることを示したい。 BCでこれを達成する方法はありますか?
答え1
私の質問に答えるために、bcで宣言されていない変数を無効とマークすることに加えて、他の人に役立つ場合に備えて動作する解決策を思い出しました。 bc 実行される式はまず sed コマンドを介してパイプされます。このコマンドは、式から保持されているbcワードを削除します。残りの変数名は宣言されていない変数とみなされ、式全体がbcで実行されたときにエラーを強制する文に変換されます。 (私は「1/0」を選択しましたが、エラーフラグのどれでも多くの選択肢を設定できます。)
ランタイム「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