リポジトリと一致し、情報を標準入力として返します。

リポジトリと一致し、情報を標準入力として返します。

だから私は本当にここに閉じ込められています。次の形式の数百万行のデータを含むいくつかのファイルを取得しました。

username|process name|process time (in minutes)

ほぼ340万のデータ行があります。今私の仕事は、これらすべてのデータをすばやく閲覧できるスクリプトを書くことです。

したがって、デフォルトではコマンドラインでユーザー名を入力し、そのユーザー名のすべてのデータ行を抽出して追加してから表示します。これは、ユーザーの総処理時間と、このユーザーの総プロセス数と同じ意味です。

これが私が今まで持っているものなのに多くはない。

tput cup 19 10
read -p "Please Enter a UserName: " uname

それが私が持っているすべてです。どうすればいいのか知っている人はいますか?

答え1

これを例の入力ファイルとして使用しましょう。

$ cat file
jim|process1|23
bob|process2|5
jim|process3|7

awkを使う

それでは、次のシェルスクリプトを書いてみましょう。

$ cat script.sh
#!/bin/sh
read -p "Please Enter a UserName: " uname
awk -v n="$uname" -F\| '$1==n{total+=$3} END{printf "Total for %s is %s minutes\n",n,total}' file

たとえば、Jim が使用する時間を要約します。

$ sh script.sh
Please Enter a UserName: jim
Total for jim is 30 minutes

どのように動作しますか?

awk は入力ファイルの各行を暗黙的に繰り返します。スクリプトは、nユーザー名とtotalユーザーが使用した合計時間(分)という2つの変数を使用しますn

  • -v n="$uname"

    これにより、awk変数が作成され、nここにシェル変数の値が割り当てられますuname

  • -F\|

    これはawkに|フィールド区切り文字として使用するように指示します。

  • $1==n{total+=$3}

    最初のフィールドが$1ユーザー名と一致するたびに、3番目のフィールドの量だけn合計が増えます。total$3

  • END{printf "Total for %s is %s minutes\n",n,total}

    ファイルの読み取りが終わったら、結果を印刷します。

シェルを使う

あるいは、シェルでループを実行することもできます。

$ cat script2.sh 
#!/bin/sh
read -p "Please Enter a UserName: " uname
while IFS=\| read -r name process minutes; do
    [ "$name" = "$uname" ] && total=$((total+minutes))
done <file
echo "Total for $uname is $total minutes"

デモとして:

$ sh script2.sh
Please Enter a UserName: jim
Total for jim is 30 minutes

どちらの方法も時間がかかりませんでしたが、この方法はよりawk速いと予想されます。

関連情報