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="[\(\):,]"}: 调用awk,使用( ) :,作为分隔符来分隔你的字段
  • /client_id/ {:仅对包含的行执行以下操作client_id
  • for (i=1; i<NF; i++) {: 遍历每一行的字段,一次一个字段
  • if ($i == "client_id") { cid = $(i+1) }: 如果我们当前所在的字段是client_id,那么它的值就是按顺序排列的下一个字段。
  • else if ($i == "id") { id = $(i+1); print cid OFS id;}: 否则,如果我们当前所在的字段是id,则将这对打印client_id : idstdout
  • 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 的方法。

解析.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 回答