私の究極の目標は、すべてのファイルから各ユーザー名のインスタンスを計算するスクリプトを作成することです。
ユーザー名は、「login」という文字列の後に続く引用符で囲まれた文字列です。たとえば、ファイルに次のものがあるとします。
{"this":"is', {"a":"strange"}, "type":{"of":"object", "but":"please"},
"go":"withit", "login":"username1"}
{"this":"is', {"login":"username2"}, "type":{"of":"object", "but":"please"},
"go":"withit"}
他のファイルには次のものがあります。
{"this":"is', {"a":"strange"}, "type":{"of":"object", "but":"please"},
"go":"withit", "login":"username3"}
{"login":"username1", "please":"gowithit"}
この場合、各ユーザー名がファイルに表示される回数を含むdictオブジェクトを含むtxtファイルが必要です。
{"username1": 2, "username2":1, "username3":1}
私はいろいろ読んだ。もの到着得る私スタート、しかし合うことはできないようです。擬似コーディングをしましたが、この時点ではこれ以上進めません。
私の考えでは、これを2つのステップに分けて行う必要があると思います。
1) すべてのユーザー名のリストを取得します。
2)各ユーザー名がすべてのファイルに表示される回数を数えます。
タスク1)の場合:
grep 'login:' * | sed 's/^.*: //'
#Except I think this gets everything from the line after 'login', which isn't what I want.
タスク2)の場合:
for all_usernames_in_file:
stringval = username_read_from_saved_file
cat * | grep -c $stringval > output.txt
誰でもここに持って行けますか?
編集する:
私はこれをしなければならないという意味です。
grep -o 'login":"[^"]*"' /path/to/dir/* | cut -d'"' -f3 | sort | uniq -c | sed '1i{ s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}' > output.txt
編集2:まだ動作しません。各命令がどのような役割を果たしているのかを理解して診断してみたいと思います。
この部分から始めるとしましょう。
grep -o 'login":"[^"]*"' /path/to/dir/* | cut -d'"' -f3 | sort | uniq -c > myfile.txt
今myfile.txt
空です。
私はコマンドが次のことをしていると思います。
grep -o
一致する行の空でない部分と一致します。
'login":"[^"]*"'
grep が一致させる文字列です。真ん中にある[^"]
ものは、等しくない後のすべての文字と一致します。これは、すべての長さの一致を望むことを意味します。つまり、ユーザー名の長さは重要ではなく、引用符の間にすべてが必要です。login":"
"
*
|
パイプラインだ。 「じゃあ」という意味
cut -d '"' -f3
login":"
区切り文字を使用して返された行(以降のすべての項目)を分割し、"
フィールド3(ユーザー名のみ)を使用することを意味します。
|
パイプラインだ。 「じゃあ」という意味
sort
ユーザー名
|
パイプラインだ。 「じゃあ」という意味
一意のユーザー名を取得し、各ユーザー名の発生回数を計算します。
そのように多くの数を取り、> myfile.txt
最後にaを追加すると、ユーザー名と各ユーザー名の発生回数を含むtxtファイルが生成されます。形式がうまく指定されていませんがあります。
なぜそのようなファイルを取得できないのですか?
注:.json.gz
フォーマットされたファイルを検索しても問題はありますか?検索時に機能するスクリプトを取得しましtxt
たが、他の形式では機能しません。
答え1
ログインと値を常に空白なしで二重引用符で囲むと仮定すると、これはgrepとcountの構成です。
grep -o 'login":"[^"]*"' * | cut -d'"' -f3 | sort | uniq -c
これにより、複数回発生したログインのリストが生成されます。
これに基づいて、必要なjson形式を設定する必要があります。sed
あなたのためにこれを行うことができます:
| sed '1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}'
これによりチャンクの開始と終了がsed
配置され、出力が目的のjson形式に変更されます。{
}
uniq
UPD:最終コマンドは次のようになります。
grep -o 'login":"[^"]*"' * | cut -d'"' -f3 | sort | uniq -c | sed '1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}' > file.txt
答え2
すべてのユーザー名、つまり次にlogin
関連するすべての文字列を取得します。正しい形式のJSONドキュメント、文書構造を知らない:
jq -r '..|select(.login?).login' file.json
これを複数のJSONファイルに適用し、結果を並べ替えて計算します。
jq -r '..|select(.login?).login' *.json | sort | uniq -c
ここで使用される表現jq
は
..
:すべてのキーと値を再帰的に巡回します。select(.login?)
:キーを含む見つかったオブジェクトを選択しますlogin
。.login
:キーの値を取得します。
jq
上記の表現に基づいて、希望する辞書は次のとおりです。
jq -sr '[..|select(.login?).login]|group_by(.)|map({key:.[0],value:length})|from_entries' *.json
テスト:
$ cat file.json
{"this":"is", "A":{"login":"username2"}, "type":{"of":"object", "but":"please"},
"go":"withit", "login":"me"}
$ jq -sr '[..|select(.login?).login]|group_by(.)|map({key:.[0],value:length})|from_entries' file.json
{
"me": 1,
"username2": 1
}
同じファイルを2回提供します。
$ jq -sr '[..|select(.login?).login]|group_by(.)|map({key:.[0],value:length})|from_entries' file.json f
ile.json
{
"me": 2,
"username2": 2
}
単一ラインのコンパクトな出力を得るには、jq
withを使用します。-c
サンプルファイルの場合、jq -sr '[..|select(.login?).login]' file.json
次のものが生成されます。
[
"me",
"username2"
]
これでgroup_by(.)
与えられる
[
[
"me"
],
[
"username2"
]
]
このmap({key:.[0],value:length})
セクションでは、以下を提供します。
[
{
"key": "me",
"value": 1
},
{
"key": "username2",
"value": 1
}
]
最後に、from_entries
最終結果が提供されます。
答え3
正規表現マッチで入力されたPerlハッシュを使用する方法は、JSONモジュールを使用して以下を変換できます。
$ perl -MJSON -lne '$h{$1}++ for /(?<="login":")(.*?)(?=")/g }{ print encode_json \%h' file1 file2
{"username3":1,"username2":1,"username1":2}
答え4
@rushの使用がsed
私のシェルで動作しなかったので、これをしました。
grep -Poh '(?<=login":")[^"]*' json* | sort | uniq -c | awk -v OFS=': ' 'BEGIN{print "{"}{print $2, $1}END{print"}"}' | sed -E 's/([0-9])$/\1,/g;s/:/\":/g;s/^([^{}])/\"\1/g'
sed
シェルがステートメント内でエスケープおよび印刷を許可している場合は、"
倍数を変更できます。awk
grep -Poh '(?<=login":")[^"]*' json* | sort | uniq -c | awk -v OFS=': ' 'BEGIN{print "{"}{print \"$2\", $1}END{print"}"}' | sed -E 's/([0-9])$/\1,/g'
awk
2番目のスクリプトでは、私の殻は窒息しました。\"
なぜかわからないが、誰かが私に教えてくれると確信しています。
私も試してみましたが、jq
jsonファイルで停止しました。構文エラーがあるようです。
"this":"is' #is written so I edited these to
"this":"is"
jq
私もこのような仕組みは気に入らないですね。
{"a":"strange"} # so I also edited these to
b: {"a":"strange"}
jq
これは、元のファイルが編集した内容と一致する必要がある場合に機能します。
jq '.login' json* | sort | uniq -c | awk -v OFS=': ' 'BEGIN{print "{"}{print $2, $1}END{print"}"}' | sed -E 's/([0-9])$/\1,/g'