ログファイルがあります。特定の数字を持つ各行について、この行の最後の数字の合計を計算したいと思います。 grepとcutを使用すると問題はありませんが、数値の合計を計算する方法がわかりません。 StackExchangeでいくつかの解決策を試しましたが、私の場合はうまくいきませんでした。
これが私が今まで持っているものです:
grep "30201" logfile.txt | cut -f6 -d "|"
30201これは私が探している行です。
最後の数字650、1389、945を追加したいです。
ログファイル.txt
Jan 09 2016|09:15:17|30201|1|SL02|650
Jan 09 2016|09:15:18|43097|1|SL01|945
Jan 09 2016|09:15:19|28774|2|SB03|1389
Jan 09 2016|09:16:21|00788|1|SL02|650
Jan 09 2016|09:17:25|03361|3|SL01|945
Jan 09 2016|09:17:33|08385|1|SL02|650
Jan 09 2016|09:18:43|10234|1|SL01|945
Jan 09 2016|09:21:55|00788|1|SL02|650
Jan 09 2016|09:24:43|03361|3|SB03|1389
Jan 09 2016|09:26:01|30201|1|SB03|1389
Jan 09 2016|09:26:21|28774|2|SL02|650
Jan 09 2016|09:26:25|00788|1|SL02|650
Jan 09 2016|09:27:21|28774|2|SL02|650
Jan 09 2016|09:29:32|30201|1|SL01|945
Jan 09 2016|09:30:12|34032|1|SB03|1389
Jan 09 2016|09:30:15|08767|3|SL02|650
答え1
追加に適した形式でpaste
数値をシリアル化するのに役立つように依頼できます。bc
% grep "30201" logfile.txt | cut -f6 -d "|"
650
1389
945
% grep "30201" logfile.txt | cut -f6 -d "|" | paste -sd+
650+1389+945
% grep "30201" logfile.txt | cut -f6 -d "|" | paste -sd+ | bc
2984
PCREがある場合は、積極的なリバースのみを使用してこれを実行grep
できます。grep
% grep -Po '\|30201\|.*\|\K\d+' logfile.txt | cut -f6 -d "|" | paste -sd+ | bc
2984
単独で使用awk
:
% awk -F'|' '$3 == 30201 {sum+=$NF}; END{print sum}' logfile.txt
2984
-F'|'
フィールド区切り記号を次のように設定します。|
$3 == 30201 {sum+=$NF}
3番目のフィールドが次の場合は、最後のフィールドの値を追加します。30201
END{print sum}
sum
印刷END
答え2
grepとcutコマンドには何の問題もありません。検索パターンとして「|30201|」を使用すると、より強力になります。次の問題は出力を処理することです。
バッシュ使用:
#!/bin/bash
# get the output as a bash array and add the elements
nums=( $(grep "|30201|" logfile.txt | cut -f6 -d "|") )
total=0
for i in ${!nums[@]}
do
total=$(($total+${nums[i]}))
done
echo $total
答え3
カンクンソリューション。
#!/bin/bash
pa=0 ; s=0 ;
while read a b ; do \
if [ "$a" == "$pa" ] ; then \
s=$(($s+$b)) ;
else
if [ "$pa" != 0 ] ; then \
echo $pa $s ;
fi ;
pa=$a ; s=$b ;
fi ;
done < <(cat j.txt | awk -F'|' '{printf("%s %s\n",$3,$6)}' | sort -n)
echo $pa $s
以前のAとSUMの初期化
フィールド 3 と 6 への入力を減らし、数値でソート
フィールド 3 が変更されない限り繰り返し、フィールド 6 を SUM に追加します。
フィールド 3 が変更されたが前の A が 0 でない場合は、前の A と SUM を出力し、前の A を a に再初期化し、最後に読み取ったフィールド 6 に SUM を再初期化します。
最後の前のAとSUMを出力します。
入力が与えられると出力:
00788 1950
03361 2334
08385 650
08767 650
10234 945
28774 2689
30201 2984
34032 1389
43097 945
答え4
私はsumcolと呼ばれる小さなツールを持っています。
#!/bin/sh
# Icarus Sparry. Free for any use.
C=${1:?"missing required column number"}
shift
awk '{s+=$'"$C"'} END { print s }' "$@"
これにより、指定したスペースで区切られた列が合計されます。書くことはできますが(@heemaylがそうであるように)
awk -F'|' '$3 == 30201 {s+=$6} END{ print s}' logfile.txt
OPの質問では、彼は次のものを使用できます。
grep "30201" logfile.txt | cut -f6 -d "|" | sumcol 1
または
grep "30201" logfile.txt | tr "| " " _" | sumcol 6