我对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
我可以用
打印exeawk -F '/' '{ print $3}'
但不确定如何用它打印uid。
一个包含uid和exe列的文件,其中只包含字符串/ bio / e.g。
506 toolx
505太多
任何帮助表示赞赏。
答案 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循环中。