awk正则表达式提取部分网址

时间:2015-12-02 19:19:48

标签: regex awk

我对awk很新。我有多个包含与

类似的行的文件
xyz msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/python/bin
abc msg=(1448783938.658:149777):   uid=506   comm="abc.py"   exe="/install/bio/toolx/bin
abc msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/bio/tooly/bin

我需要两个输出。 一个。一个文件只包含所有文件中的uid和exe列(就在/ install /之后) e.g

505 python
506 bio
505 bio

我可以用

打印exe
awk -F '/' '{ print $3}'

但不确定如何用它打印uid。

  1. 一个包含uid和exe列的文件,其中只包含字符串/ bio / e.g。

    506 toolx

    505太多

  2. 任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:4)

您可以使用以下awk命令:

awk -F'[[:space:]="/]+' '{print $5, $10}' file

我正在使用一组分隔符。这使得访问感兴趣的值变得简单。但是,仅当路径不包含<space>="/时,它才有效。

顺便说一下,也可以使用sed,无论路径中是否有任何类型的字符都可以使用,因为没有使用分隔符:

sed -r 's~.*uid=([^[:space:]]+).*exe="/install/([^/]+).*~\1 \2~' file

答案 1 :(得分:1)

类似的awk解决方案

$ awk -F" +|[=/]" '{print $5,$11}' bio
505 python
506 bio
505 bio

答案 2 :(得分:1)

我会保持简单并使用默认字段分隔符 - 然后使用 sub split 清理每个字段以进行打印。这是拆分解决方案。

awk '{ split($3, uid, "="); split($5, exe, "/"); print uid[2], exe[3] }'

以下是如何开发的:

$ echo 'xyz msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/python/bin' | awk '{ print $3, $5 }'
uid=505 exe="/install/python/bin
$ echo 'xyz msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/python/bin' | awk '{ split($3, uid, "="); print uid[2], $5 }'
505 exe="/install/python/bin
$ echo 'xyz msg=(1448783938.658:149777):   uid=505   comm="abc.py"   exe="/install/python/bin' | awk '{ split($3, uid, "="); split($5, exe, "/"); print uid[2], exe[3] }'
505 python

我首先尝试了基于 sub 的解决方案,但结果却比基于 split 的解决方案更长,更神秘 - 拆分解决方案似乎更直接。 (如果基于 sub 的解决方案是合理的,那么 sed 可能是更好的候选语言。)

应该添加的一件事是一些过滤器,以确保我们只处理有效的行,这可以像下面这样简单:

awk '$3 ~ /uid=/ && $5 ~ /exe="\/install\// { split($3, uid, "="); split($5, exe, "/"); print uid[2], exe[3] }'

另一件事......如果你的文件中的uid和exe字段在列之间移动,你将不得不使用for循环来搜索它们......这足够长,可以变成像这样的脚本文件以下内容:

#! /usr/bin/awk -f
{
        u=0
        e=0
        for (i=1; i<=NF; i++) {
                if ($i ~ /uid=/)
                        u=i
                else if ($i ~ /exe="\/install\//)
                        e=i
                if (u && e)
                        break
        }
        if (!u || !e)
                next
        split($u, uid,"=")
        split($e, exe, "/")
        print uid[2], exe[3]
}

在这种情况下,检查我们在前一个示例中放入的有效性的前导模式是否嵌入到for循环中。