在模式之后提取字符串

时间:2012-11-20 00:41:13

标签: unix sed awk pattern-matching

我想在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 个答案:

答案 0 :(得分: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

答案 1 :(得分: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 : id对打印到stdout
  • input_file_name:提供输入文件的名称作为awk脚本的第一个参数。

答案 2 :(得分: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删除引入的换行符。

答案 3 :(得分:2)

我更喜欢awk,但是如果你想知道如何用sed做这个,这里有一种适用于GNU sed的方法。

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]+)

最后的替换会从循环中移除遗留物。