Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 在模式后提取字符串_Unix_Sed_Awk_Pattern Matching - Fatal编程技术网

Unix 在模式后提取字符串

Unix 在模式后提取字符串,unix,sed,awk,pattern-matching,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

我想提取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。但我不知道具体怎么做

谢谢

这可能适合您:

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

下面是一个有效的
awk
脚本(我把它放在多行上,让它更详细一点,这样你就可以看到发生了什么):

说明:

03 204
03 491
03 29
04 209
04 301
05 20
  • awk'BEGIN{FS=“[\(\):,]”
    :调用
    awk
    ,使用
    作为分隔字段的分隔符
  • /client\u id/{
    :仅对包含
    client\u id的行执行以下操作:

  • for(i=1;i我更喜欢awk,但如果您想知道如何使用sed实现这一点,这里有一种使用GNU sed的方法

    解析

    /client\u id/{
    :a
    s/(客户id:([0-9]+)[^(+\(id:([0-9]+)([^\n]+)(.*)/\1\4\5\n\2\3/
    助教
    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//; }'
    
    说明: 其思想是反复匹配
    客户机id:([0-9]+)
    id:([0-9]+)
    对,并将它们放在模式空间的末尾。每次传递时,
    id:([0-9]+)
    都会被删除

    最后的替换将删除循环中的剩余部分。

    这可能适合您(GNU-sed):

    • /.*(\(客户端id:([0-9]+)[^(]*\(id:([0-9]+)/!d
      如果行没有预期的字符串,请删除它
    • s//\2\3\n\1/
      通过复制
      client\u id
      并向前移动第一个
      id
      来重新安排行,从而减少连续迭代的行数
    • P
      打印到引入的换行符
    • D
      删除到引入的换行符

    +1表示基于FS的方法,但我认为
    '{print$2,$6}'
    是您在正文中所需的全部内容。谢谢Ed。我认为需要一个循环,因为存在多个“相关用户”。我想,
    $6
    只会打印第一个的id。不错,但我的呆瓜抱怨它决定忽略括号前的``。这些可以安全地删除。不允许再编辑我自己的评论…我想添加的内容:字符集字符(
    [
    ]
    ),只有以下是需要转义的元字符:
    \^]-
    。一些建议:去掉空语句(尾随分号)将
    print cid of s id
    更改为简单地
    print cid,id
    (OFS的存在就是为了这个),不要在前面放\和在字符集中,由于client_id始终位于同一位置,您可以简单地将其设置为$3,然后从4开始循环。请参阅@steve's solution.Sampson,感谢您的详细解释。还有一个问题,关于行/client_id/{,如果我写/client_id/和{在两个不同的行中,输出混合了输入文件和正确的结果。为什么?@jerry这只是
    awk
    语法的一部分。简短的回答是:如果在awk脚本的同一行中最外层的
    {
    前面没有任何内容,则括号内的指令将对每一行执行。例如
    BEGIN{…}
    表示“仅在脚本开始时执行此操作”
    /pattern/{…}
    表示仅在具有“pattern”的行上执行此操作。对于注释框来说,长而正确的答案应该解释得太长。Thor,感谢您的详细解释。还有一个问题,关于行/client\u id/{,如果我写/client\u id/和{在两个不同的行中,输出混合了输入文件和正确的结果。为什么?@jerry:这很奇怪,我在这里得到一个错误
    sed:file parse.sed第2行:未知命令
    ,后跟一个换行符。据我所知,大括号需要与前面的条件在同一行。
    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
    
    sed -r '/.*(\(client_id:([0-9]+))[^(]*\(id:([0-9]+)/!d;s//\2 \3\n\1/;P;D' file