web-dev-qa-db-ja.com

ファイル内の1行に1つずつ、数式を評価するにはどうすればよいですか?

次のファイルがあります。

37 * 60 + 55.52
34 * 60 + 51.75
36 * 60 + 2.88
36 * 60 + 14.94
36 * 60 + 18.82
36 * 60 + 8.37
37 * 60 + 48.71
36 * 60 + 34.17
37 * 60 + 42.52
37 * 60 + 51.55
35 * 60 + 34.76
34 * 60 + 18.90
33 * 60 + 49.63
34 * 60 + 37.73
36 * 60 + 4.49

このファイルの各行で方程式を評価し、結果を出力するシェルコマンドまたはBashスクリプトを記述する必要があります。たとえば、1行目では2275.52印刷されました。各結果は1行に1回印刷されます。

私はもう試した cat math.txt | xargs -n1 expr、ただしこれは機能しません。 awkがこれを実行できるようにも思えますが、そのコマンドの構文に慣れていないので、どうなるかわかりません。

8
void.pointer

これはawkでうまくいくようです:

while IFS= read i; do 
  awk "BEGIN { print ($i) }"
done < math.txt

から ここ

($i)のような算術式の問題を回避するために、$iではなく1 > 2を使用していることに注意してください(print 1 > 212というファイルに出力し、print (1 > 2)はその算術式の結果である0を出力します)。

$iシェル変数の展開はawkによってcodeとして解釈されることになるため、これは本質的にコードインジェクションの脆弱性。ファイルに有効な算術式のみが含まれていることを保証できない場合は、いくつかの入力検証を配置する必要があります。たとえば、ファイルにsystem("rm -rf ~")行がある場合、それは劇的な結果をもたらす可能性があります。

13

ここが私がそれが最善の方法であるかどうかわからないものです

bc < toto 

データで何をしたいかに応じて

francois@zaphod:~$ cat > toto
37 * 60 + 55.52
34 * 60 + 51.75
36 * 60 + 2.88
36 * 60 + 14.94
36 * 60 + 18.82
36 * 60 + 8.37
37 * 60 + 48.71
36 * 60 + 34.17
37 * 60 + 42.52
37 * 60 + 51.55
35 * 60 + 34.76
34 * 60 + 18.90
33 * 60 + 49.63
34 * 60 + 37.73
36 * 60 + 4.49
francois@zaphod:~$ while read ; do echo " $REPLY" | bc  ; done < toto
2275.52
2091.75
2162.88
2174.94
2178.82
2168.37
2268.71
2194.17
2262.52
2271.55
2134.76
2058.90
2029.63
2077.73
2164.49
francois@zaphod:~$

bCコマンドがないと、10進値を使用できません。

francois@zaphod:~$ while read ; do echo $(( "REPLY" )) ; done < toto
-bash: 37 * 60 + 55.52: syntax error: invalid arithmetic operator (error token is ".52")
francois@zaphod:~$
8
francois P

Perlを使用している場合:

Perl -ne 'print eval $_,"\n"' math.txt

(私はこれを使用して私のラップトップで毎秒50000行を取得します)。

7
Ole Tange

old-good Pythonの場合:

$ python -c $'import sys;\nfor line in sys.stdin:print(eval(line))' <math.txt
2275.52
2091.75
2162.88
2174.94
2178.82
2168.37
2268.71
2194.17
2262.52
2271.55
2134.76
2058.9
2029.63
2077.73
2164.49
4
RomanPerekhrest

結果だけが必要な場合は、 @ francois-p が提供する答えが得られます

楽しみとゲームのために、pastesedを追加します:

$ paste <(sed 's/\($\)/\1\t=/g' somefile) <(bc < somefile)
37 * 60 + 55.52 =   2275.52
34 * 60 + 51.75 =   2091.75
36 * 60 + 2.88  =   2162.88
36 * 60 + 14.94 =   2174.94
36 * 60 + 18.82 =   2178.82
36 * 60 + 8.37  =   2168.37
37 * 60 + 48.71 =   2268.71
36 * 60 + 34.17 =   2194.17
37 * 60 + 42.52 =   2262.52
37 * 60 + 51.55 =   2271.55
35 * 60 + 34.76 =   2134.76
34 * 60 + 18.90 =   2058.90
33 * 60 + 49.63 =   2029.63
34 * 60 + 37.73 =   2077.73
36 * 60 + 4.49  =   2164.49
3
markgraf

Perlの場合:

Perl -ple '$_=eval' ex
Perl -nE 'say eval' ex

pythonの場合:

python3 -qi < ex
python3 -qic 'import sys; sys.ps1=""' < ex

Haskellの場合:

ghci < ex
ghci < ex | grep -Po '> \S+$'

計算あり:

calc -f ex      # apt install apcalc if necessary
3
JJoao

bash/kshに直接(Edit:結局のところ、bashはこれを行うことができません。 kshのみ-これを指摘してくれてありがとう):

_$ while read l
> do
> echo $(($l))
> done <<!
> 37 * 60 + 55.52
> 34 * 60 + 51.75
> 36 * 60 + 2.88
> 36 * 60 + 14.94
> 36 * 60 + 18.82
> 36 * 60 + 8.37
> 37 * 60 + 48.71
> 36 * 60 + 34.17
> 37 * 60 + 42.52
> 37 * 60 + 51.55
> 35 * 60 + 34.76
> 34 * 60 + 18.90
> 33 * 60 + 49.63
> 34 * 60 + 37.73
> 36 * 60 + 4.49
> !
2275.52
2091.75
2162.88
2174.94
2178.82
2168.37
2268.71
2194.17
2262.52
2271.55
2134.76
2058.9
2029.63
2077.73
2164.49
_

これには、ごく最近のバージョンのシェルが必要になる場合があります-$((...))は、整数演算のみを行うために使用されます。

2
j4nd3r53n

awk/pythonの使用:

python -c "$(awk '{printf "print %s;", $0}' math.txt)"

ここではawkを使用して、ファイルをpythonが受け入れる入力にフォーマットし、その後pythonが処理を実行しています。

あるいは、Perlはほとんど同じ方法で使用できます。

Perl -le "$(awk '{printf "print %s;", $0}' math.txt)"
2
jesse_b

awkを直接使用:

awk '{ printf "%f\n", $0 }' math.txt

$0は、ファイルから1行ずつ読み取られる行全体を表します。

さらに、厄介な注射の影響を受けません。行を浮動小数点数としてのみ評価します。

1

混乱をbc -lにフィードするだけで、式の行ごとに1行の結果が返されます。 (-lは数学ライブラリをロードします。また、scaleをより高い値に設定するため、小数の結果が得られます。)

0
vonbrand