【问题标题】:awk/sed/grep extract part of lines with specific patternawk/sed/grep 提取具有特定模式的部分行
【发布时间】:2015-10-06 00:19:00
【问题描述】:

我正在尝试提取文件的确定部分,如下所示:

1443113312 mongo client connection created with mongodb://172.28.128.5:27017
1443113312 [OVERALL], RunTime(ms), 4864.0
1443113313 [READ], Return=0, 485
1443113313 [CLEANUP], 99thPercentileLatency(us), 4487.0
1443113314 [UPDATE], 99thPercentileLatency(us), 27743.0

这是我期待的输出:

mongodb://172.28.128.5 Operations=OVERALL 1443113312
mongodb://172.28.128.5 Operations=READ    1443113313
mongodb://172.28.128.5 Operations=CLEANUP 1443113313
mongodb://172.28.128.5 Operations=UPDATE  1443113314

我非常感谢任何建议。谢谢。

【问题讨论】:

  • 建议:解释你想用来将输入转换为输出的算法。伪代码就好了。

标签: awk sed grep


【解决方案1】:
$ awk -F'[][ \t:]+' '/mongodb/{a=$(NF-2)":"$(NF-1);next} a{printf "%s Operations=%-7s %s\n",a,$2,$1}' file
mongodb://172.28.128.5 Operations=OVERALL 1443113312
mongodb://172.28.128.5 Operations=READ    1443113313
mongodb://172.28.128.5 Operations=CLEANUP 1443113313
mongodb://172.28.128.5 Operations=UPDATE  1443113314

工作原理

  • -F'[][ \t:]+'

    这会将字段分隔符设置为空格、制表符、冒号或方括号 ([]) 的任意组合。

  • /mongodb/{a=$(NF-2)":"$(NF-1);next}

    如果该行包含mongodb,那么我们将第三个和倒数第二个字段保存在变量a中。

  • a{printf "%s Operations=%-7s %s\n",a,$2,$1}

    如果变量a 已被赋值,则根据问题打印出当前重新格式化的值。

变化

这会产生 mongo 字符串,但不会产生 IP,并将操作放在括号中:

$ awk -F'[][ \t:]+' '/mongodb/{a=$(NF-2);next} a{printf "%s\tOperations=\"%s\"\t%s\n",a,$2,$1}' file
mongodb Operations="OVERALL"    1443113312
mongodb Operations="READ"       1443113313
mongodb Operations="CLEANUP"    1443113313
mongodb Operations="UPDATE"     1443113314

【讨论】:

  • 谢谢。我花了一些时间学习 sed,尽管最后我完全糊涂了。我发现 awk 更容易理解。
  • 只是一个简单的修改。如果我只想获取没有 IP 的 "mongodb" 字符串并将操作值放在像 Operation="READ" 的双引号内怎么办!?
  • @Araz 非常好:我添加了一个变体,消除了 IP 并在操作周围加上引号。
【解决方案2】:

Perl 来救援!

perl -nwe 'if (m=mongo client connection created with (mongodb://[0-9.]+)=) {
               $url = $1;
           } elsif (/^([0-9]+) \[([[:upper:]]+)\]/) {
               print "$url Operations=$2 $1\n";
           }' input-file

解释:-n 逐行读取输入。每次遇到“created”字符串时,URL 都会保存在 $url 变量中。每次遇到数字(时间戳?)加上方括号中的大写单词时,都会打印带有操作和时间戳的 URL。

【讨论】:

    【解决方案3】:

    这可能对你有用(GNU sed 和 printf):

    sed -rn '\|://|h;G;s/^(\S+) \[(\S+)\].* (\S+):.*/printf "%s Operations=%-7s %s" \3 \2 \1/ep' file
    

    这使用 GNU sed 的 e 标志来评估模式空间。或者,可以通过将printf 命令传送到外壳,在单独的过程中完成评估,因此:

    sed -rn '\|://|h;G;s/^(\S+) \[(\S+)\].* (\S+):.*/printf "%s Operations=%-7s %s\n" \3 \2 \1/p' | sh
    

    【讨论】:

    • 谢谢。不错的解决方案:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    • 2012-06-20
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 2019-04-19
    相关资源
    最近更新 更多