このコマンドの各部分が何を行うかは既にわかっています。
zgrep -v "org" /path/to/files/* | zgrep "FollowEvent" | zgrep -o 'login":"[^"]*"' | cut -d'"' -f3 | sort | uniq -c | sed '1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}' > usernames_followevents.txt
一つずつ:
1)ファイルを検索するためzgrep
に使用されるgrep
.json.gz
2) はzgrep -v "org" /path/to/files/*
、 の各ファイル内で を/path/to/files/*
含まないエントリを検索することを意味します"org"
。
3) は|
パイプです。「そして」という意味です。
4) は、最初の zgrep で見つかった結果内でzgrep "FollowEvent"
文字列を検索することを意味します。"FollowEvent"
5) は|
パイプです。「そして」という意味です。
6)は、エントリ内のzgrep -o 'login":"[^"]*"'
文字列login":"
と単語「login」に続くすべてのテキストの空でない一致を検索することを意味します。
7)| cut -d'"' -f3
は、「結果の一致から 3 番目のフィールドのみを取得する」ことを意味し、この場合はユーザー名です。
8) は| sort | uniq -c
、「ユーザー名を並べ替え、各ユーザー名の一意のインスタンスの数を数える」ことを意味します。
これまでのところ、次のとおりです。
zgrep -v "org" /path/to/files/* | zgrep "FollowEvent" | zgrep -o 'login":"[^"]*"' | cut -d'"' -f3 | sort | uniq -c
これは、/path/to/files/* 内のすべてのファイルのすべてのエントリで、文字列 "org" は含まれず、文字列 "FollowEvent" は含まれているすべてのユーザー名 ("login" に続く 3 番目のフィールドのテキスト) を検索し、これらのユーザー名を並べ替えて、各ユーザー名の出現回数をカウントします。
私の問題はこの部分にあります:
sed '1i{ s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}'
私はこれだけは知っています(または知っていると思っています)。
1) はsed
、テキストの操作を可能にするストリーム エディターです。
2) はsed '1i{
「前の行に{を挿入する」という意味です。
3) このコマンドは、{"username":count of that username}
前述したように、すべてのファイル内のすべてのユーザー名を返します。次に、これらを というファイルに格納しますusernames_followevents.txt
。
4) この部分は"\2":
、「2 番目のフィールド (?) であるユーザー名を二重引用符で囲み、その後に : を挿入する」という意味です。
コマンドを操作したいのですsed
が、残りの詳細を理解しなければ変更を開始できません。
コマンドの各部分sed
が何をしているのか説明していただけますか?
答え1
現在の sed コマンドの記述方法は正しくありません。次のスクリプトのいずれかにする必要があります。
1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/
$a}
または、次のように 1 行で記述することもできます。
sed -e '1i{' -e 's/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/' -e '$a}'
i
文字通り、コマンドの後、改行または式の終わり (-e を使用) まで入力したすべての内容がa
標準出力に直接印刷されます。
それが何をするのか、詳しく説明しましょう:
1i{
1
は行アドレスです。これは、sed にコマンドを実行するタイミングを伝えます。最初の行の内容がパターン スペースに読み込まれると (末尾の改行なしで)、i
標準出力に別の行に '{' が挿入されます。パターン スペースは変更されず、'{' が追加されていないことに注意してください。
s
は、sed で最も用途の広いコマンドである検索と置換のコマンドです。\s
空白に一致します。\(regex\)
数学のように内部の正規表現をグループ化しますが、一致したものをそのグループの順序 (\1 から \9) に基づいて数値レジスタに格納します。
の出力はuniq -c
次のようになります。
occurrences string
3 user
さて、複雑な部分です:
\s*\([0-9]*\)\s*\(.*\)
まだ 1 行目です。パターン スペースは、スペースの束、次に '3 user' です。これに一致させるには、空白を 0 回以上検索し、次に数字を複数回検索します。これは、レジスタ \1 に格納されている数値です (私の意見では、* ではなく + であるべきでした)。次にスペース (* は必要ないと思います)、次に任意の文字を複数回検索します (この場合も + のほうが適切でした)。これは、レジスタ \2 に格納されています。つまり、発生は \1 にあり、文字列/ユーザーは \2 にあります。
"\2": \1,
行全体が一致し、部分が保存されたので、一致したものを引用符、ユーザー、引用符、コロン、スペース、出現、カンマの順に置き換えます。
$a}
$
行アドレスでもあります。現在の行が最後の行である場合 (現時点ではそうではありません)、a
コマンドを呼び出して、別の行に '}' を標準出力に追加します。
これはこの行のコード処理の終了であり、操作が完了した後のパターン スペースの自動印刷が行われ、次に 2 行目の内容が読み取られ、サイクル全体が繰り返されます。
出力例:
{
"user": 3,
}
これは基本的に JSON ファイル形式ですが、インデントが不適切です。
以上です。長々と書いてすみません:)