次の情報を含むテキストファイルがあります。
Game Copies_Sold(M) Release_date Genre
God_of_War 19 20/04/2018 Action-Adventure
Uncharted_4 16 10/05/2016 Action-adventure
Spider-Man 13 07/09/2018 Action-adventure
The_Witcher_3 10 18/05/2015 Action_role-playing
2番目の列の数字を合計する必要があるため、次のスクリプトを作成しました。
#!/bin/bash
file=$1
s=0
tail -n +2 $file |cut -f 2 |
{ while read line
do
s=$(( $s+$line ))
done <$file }
echo $s
しかし、明らかに私は何か間違っています。ここで何をすべきですか?ありがとうございます!
ベストアンサー1
次のようにする必要があります。
#! /bin/sh -
file=${1?}
awk 'NR >= 2 {sum += $2}; END {print sum+0}' < "$file"
アプローチに問題があります。
- 少なくとも1つの引数がスクリプトに渡されたことを確認しません(おおよそここで説明します
${1?}
)。 - 周囲に引用符がありません。
$file
--
オプションの終わりを表示するために欠落しているtail
(ニットピッキー:以下と同じ)-
シェルボーンに位置)- デフォルトの区切り文字
cut
はTABで、入力はスペースで区切られているように見えます。デフォルトawk
の区切り文字は、スペース(スペースとタブを含む)の数です。 - ループにパイプを接続し、そのループの入力をリダイレクトすることもできます
$file
。 - 以前に行方不明または
;
改行}
- 欠落している
-r
オプションread
- Bashでは、パイプの右端のコンポーネントもサブシェルで実行されるため(
lastpipe
このオプションが有効になっていない場合)、$s
パイプが返された後に変数への変更が失われます。 - しかし、まずシェルループを使用してテキストを処理しています。これは一般的に悪い習慣であり、非効率的で正しく実行するのが難しいです。。
- ここの状況もあなたほど悪いです。外部入力にシェル操作を使用すると、Bash にコマンド注入の脆弱性が発生します。。
- スクリプトにbashに関連する内容がないので、システムの
sh
。
これらのエラーのいくつかは次のとおりです。住宅検査(システムにスタンドアロンソフトウェアとしてインストールすることもできます)。
これには次のものがあります。
$ shellcheck myscript
Line 4:
tail -n +2 $file |cut -f 2 |
^-- SC2086 (info): Double quote to prevent globbing and word splitting.
Did you mean: (apply this, apply all SC2086)
tail -n +2 "$file" |cut -f 2 |
Line 5:
{ while read line
^-- SC2162 (info): read without -r will mangle backslashes.
Line 7:
s=$(( $s+$line ))
^-- SC2030 (info): Modification of s is local (to subshell caused by pipeline).
^-- SC2004 (style): $/${} is unnecessary on arithmetic variables.
^-- SC2004 (style): $/${} is unnecessary on arithmetic variables.
Line 8:
done <$file }
^-- SC2086 (info): Double quote to prevent globbing and word splitting.
Did you mean: (apply this, apply all SC2086)
done <"$file" }
Line 9:
echo $s
^-- SC2031 (info): s was modified in a subshell. That change might be lost.