web-dev-qa-db-ja.com

文の要約を作る

データがあり、結論を出すために文を要約したい。以下の例はデータとは関係ありませんが、アイデアを明確にして複製できるようにするためのものです。

Employee Suzie signed one time.
Employee Dan signed one time.
Employee Jordan signed one time.
Employee Suzie signed one time.
Employee Suzie signed one time.
Employee Harold signed one time.
Employee Sebastian signed one time.
Employee Jordan signed one time.
Employee Suzie signed one time.
Employee Suzan signed one time.

次のように、これらの文の要約を作成します。

Jordan signed 2 time(s)
Dan signed 1 time(s)
Suzie signed 4 time(s)
Suzan signed 1 time(s)
Sebastian signed 1 time(s)
Harold signed 1 time(s)

私はawkで遊んでみましたが、非常に難しいようです。それからsedを試しましたが、うまくいきませんでした。 sedは、物事を見つけて変更するためのものです。

7
user316463

一般的なアプローチは

_$ awk '{ count[$2]++ }
       END {
           for (name in count)
               printf("%s signed %d time(s)\n", name, count[name])
       }' <file
Harold signed 1 time(s)
Dan signed 1 time(s)
Sebastian signed 1 time(s)
Suzie signed 4 time(s)
Jordan signed 2 time(s)
Suzan signed 1 time(s)
_

つまり、連想配列/ハッシュを使用して、特定の名前が表示された回数を格納します。 ENDブロックで、すべての名前を反復処理し、それぞれの概要を出力します。

少し見栄えを良くするには、printf()呼び出しの_%s_プレースホルダーを_%-10s_のように変更して、名前に10文字(左揃え)を予約します。

_$ awk '{ count[$2]++ }
       END {
           for (name in count)
               printf("%-10s signed %d time(s)\n", name, count[name])
       }' <file
Harold     signed 1 time(s)
Dan        signed 1 time(s)
Sebastian  signed 1 time(s)
Suzie      signed 4 time(s)
Jordan     signed 2 time(s)
Suzan      signed 1 time(s)
_

出力をいじる(退屈しているため):

_$ awk '{ count[$2]++ }
       END {
           for (name in count)
               printf("%-10s signed %d time%s\n", name, count[name],
                      count[name] > 1 ? "s" : "" )
       }' <file
Harold     signed 1 time
Dan        signed 1 time
Sebastian  signed 1 time
Suzie      signed 4 times
Jordan     signed 2 times
Suzan      signed 1 time
_
14
Kusalananda

awkは関連付けられた配列を使用しており、これは使用しているメモリサイズに制限されますが、代わりに次のように実行できます。

sort -k2,2 infile | uniq -c

または、必要に応じてフォーマットを行います。

sort -k2,2 infile  |uniq -c |awk '{ print $3, "signed", $1, "time(s)" }'
8
αғsнιη

このジョブはawk用です。それを行うには、array[index]が必要です。

awk 'NF {name[$2]++} END{for (each in name) {print each " signed " name[each] " time(s)"}}' file

Jordan signed 2 time(s)
Dan signed 1 time(s)
Suzie signed 4 time(s)
Suzan signed 1 time(s)
Sebastian signed 1 time(s)
Harold signed 1 time(s)

NFは余分な空白行を削除するためのものです。データは配列のインデックスと値に格納されます。値は対応するインデックスで参照されます。

3
user88036

フォーマットなしの場合、最も簡単な解決策は

sort|uniq -c

uniq -cは行をカウントし、それらの行の前にそれらのカウントを付けます。uniqが機能するためにはソートが必要です。

$ sort|uniq -c
asdf
asdf
qwer
[ctrl-d]
      2 asdf
      1 qwer

正確なフォーマットが必要な場合は、sedまたはawkを使用してフォーマットできます。

awk '{print $2}'|sort|uniq -c|awk '{print($2, "signed" ,$1, "time(s)")}'
0
allo