web-dev-qa-db-ja.com

ファイルからgrepおよび数値を切り取り、それらを合計する方法

ログファイルがあります。特定の番号を持つすべての行について、それらの行の最後の数を合計したいと思います。グレップしてカットすることは問題ありませんが、数値を合計する方法がわかりません。 StackExchangeからいくつかのソリューションを試しましたが、私の場合、それらを機能させることができませんでした。

これは私がこれまでに持っているものです:

grep "30201" logfile.txt | cut -f6 -d "|"

30201は私が探している行です。

最後の650、1389、945を合計したい

Logfile.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
3
YungScholar

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}sumENDを出力します
10
heemayl

Bashソリューション。

#!/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が同じである限りループし、SUMにフィールド6を追加します

フィールド3が変更されても、前のAが0でない場合は、前のAとSUMを出力し、前のAをaに再初期化し、SUMを最後のフィールド6に読み取ります。

最後の前のAおよびSUMを出力します。

指定された入力の出力:

00788 1950
03361 2334
08385 650
08767 650
10234 945
28774 2689
30201 2984
34032 1389
43097 945
0
JdeHaan

Grepとcutコマンドには何も問題はありません。 "| 30201 |"を使用して、より堅牢にすることができます検索パターンとして。問題は出力を処理することです。

Bashの使用:

#!/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
0
Wastrel

私が保持している1つの小さなツールを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
0
icarus