7

client_id と id に続く数字を抽出し、各行で client_id と id をペアにします。

たとえば、ログの次の行では、

User(client_id:03)) results:[RelatedUser(id:204, weight:10),_RelatedUser(id:491,_weight:10),_RelatedUser(id:29, weight: 20)

User(client_id:04)) results:[RelatedUser(id:209, weight:10),_RelatedUser(id:301,_weight:10)

User(client_id:05)) results:[RelatedUser(id:20, weight: 10)

出力したい

03 204
03 491
03 29
04 209
04 301
05 20

sed または awk を使用する必要があることはわかっています。しかし、正確な方法はわかりません。

ありがとう

4

4 に答える 4

5

これはあなたのために働くかもしれません:

awk -F "[):,]" '{ for (i=2; i<=NF; i++) if ($i ~ /id/) print $2, $(i+1) }' file

結果:

03 204
03 491
03 29
04 209
04 301
05 20
于 2012-11-20T00:55:07.413 に答える
4

動作するawkスクリプトを次に示します (何が起こっているかを確認できるように、複数の行に分けてもう少し冗長にしました)。

#!/bin/bash

awk 'BEGIN{FS="[\(\):,]"}
/client_id/ {
cid="no_client_id"
for (i=1; i<NF; i++) {
    if ($i == "client_id") {
        cid = $(i+1)
    } else if ($i == "id") {
        id = $(i+1);
        print cid OFS id;
    }
 }
}' input_file_name

出力:

03 204
03 491
03 29
04 209
04 301
05 20

説明:

  • awk 'BEGIN{FS="[\(\):,]"}: を呼び出し、フィールドを区切る区切り文字としてandをawk使用します( ) :,
  • /client_id/ {: を含む行に対してのみ、次の操作を行いますclient_id
  • for (i=1; i<NF; i++) {: 各行のフィールドを一度に 1 フィールドずつ繰り返します。
  • if ($i == "client_id") { cid = $(i+1) }: 現在のフィールドが の場合、client_idその値は次のフィールドになります。
  • else if ($i == "id") { id = $(i+1); print cid OFS id;}: そうではなく、現在のフィールドが である場合はidclient_id : idペアをに出力しますstdout
  • input_file_name: 入力ファイルの名前をスクリプトの最初の引数として指定しawkます。
于 2012-11-20T01:03:45.190 に答える
3

これはうまくいくかもしれません(GNU sed):

sed -r '/.*(\(client_id:([0-9]+))[^(]*\(id:([0-9]+)/!d;s//\2 \3\n\1/;P;D' file
  • /.*(\(client_id:([0-9]+))[^(]*\(id:([0-9]+)/!d行に意図した文字列がない場合は削除します。
  • s//\2 \3\n\1/client_idをコピーして最初の行を前に移動することで行を再配置し、id連続する反復の行を減らします。
  • P導入された改行まで印刷します。
  • D導入された改行まで削除します。
于 2012-11-20T11:03:48.550 に答える
2

これには awk を使用することをお勧めしますが、sed でこれを行う方法を疑問に思っている場合は、GNU sed で動作する 1 つの方法を次に示します。

parse.sed

/client_id/ {
  :a
  s/(client_id:([0-9]+))[^(]+\(id:([0-9]+)([^\n]+)(.*)/\1 \4\5\n\2 \3/
  ta
  s/^[^\n]+\n//
}

次のように実行します。

sed -rf parse.sed infile

またはワンライナーとして:

<infile sed '/client_id/ { :a; s/(client_id:([0-9]+))[^(]+\(id:([0-9]+)([^\n]+)(.*)/\1 \4\5\n\2 \3/; ta; s/^[^\n]+\n//; }'

出力:

03 204
03 491
03 29

04 209
04 301

05 20

説明:

アイデアは、一致client_id:([0-9]+)id:([0-9]+)ペアを繰り返し、パターン空間の最後に配置することです。各パスでid:([0-9]+)が削除されます。

最後の置換により、ループから残り物が削除されます。

于 2012-11-20T08:46:04.277 に答える