如何在shell脚本中使用awk处理字符串

时间:2017-02-08 18:16:26

标签: bash shell awk ksh

我是shell脚本的新手,必须围绕它编写很多任务。我试图尽可能快地学习,但有时候shell脚本使得任务看起来很容易,而在其他时候它只是玩具和我一起玩。我现在面临着类似的情况。 我有一个命令,它给我一个像这样的输出。

 File                  Dependents
  ----------------------------------------------------------------------------
<File> is a requisite of <Dependents>
Path: /usr/lib/obj
  Java 1.0.0.0          analysis 0.0.0.2
                        runtime 1.2.0.0
                        client 1.2.0.0
                        framework 6.1.9.100
                        sguide 1.9.10.0
                        sysmgt 6.1.9.100
                        dsm 6.1.9.200

Path: /etc/obj
  Java 1.0.0.0          analysis 1.2.0.2
                        runtime 2.0.0.0
                        client3 6.1.9.0
                        sysmgt 6.1.9.0
                        dsm2 6.1.9.0

现在我想将依赖项列表放入一个数组中以便进一步处理。这是我到目前为止能够做到的:

<command> | cut -f1 | grep '[a-z]' | grep -v File | grep -v : | awk '{ print $1}'

输出是:

Java<<< I want this to be analysis
runtime
client
framework
sguide
sysmgt
dsm

Java<<< want this to be analysis
runtime
client3
sysmgt
dsm2

我必须在两个单独的数组中捕获这两个列表。

有人可以帮助我以优雅的方式实现此输出。我不想用我的暴力方法来处理这些代码,包括很多条件和比较。

2 个答案:

答案 0 :(得分:2)

awk救援!

$ arr1=$(command ... | awk -v c=1 '!NF{f=0} f && s==c{print $1} /Java/{f=1; s++; if(s==c) print $(NF-1)}')

$ arr2=$(command ... | awk -v c=2 '!NF{f=0} f && s==c{print $1} /Java/{f=1; s++; if(s==c) print $(NF-1)}')

$ echo $arr1
analysis runtime client framework sguide sysmgt dsm

$ echo $arr2
analysis runtime client3 sysmgt dsm2

如果运行一次命令并将结果拆分为两个数组,可能会更好。

<强>解释

  

awk -v c=1将awk变量c设置为1(描述组实例编号)

     

'!NF{f=0}如果没有字段(空行)重置f

     

f && s==c{print $1}如果设置了f并且计数器等于c则打印第一个字段

     

/Java/{f=1; s++;当模式与Java匹配时,设置f并增加计数器和   ...if(s==c) print $(NF-1)}'如果计数器匹配c打印倒数第二个字段。

答案 1 :(得分:1)

您可以先使用Java删除子字符串来修复解决方案:

command | sed 's/Java [^ ]*//' | cut -f1 | grep '[a-z]' | grep -v File | grep -v : | awk '{ print $1}'

使用awk时,您可以更好地使用awk的全部力量。只是说你希望打印带有数字的任何一行的倒数第二个字段:

command | awk '/[0-9]/ { print $(NF-1) }'

这比尝试使用sed更好(你有标签或空格吗?)

command | sed -n '/[0-9].[0-9]/ s/^.* \([^ ]*\) .*/\1/p'

一个有趣的解决方案是使用rev来还原您的文字。那样cut可以找到第二个字段。

command | grep '[0-9].[0-9]' | rev | cut -d " " -f2 | rev

对于只阅读最后一行的人,我将重复awk解决方案:

command | awk '/[0-9]/ { print $(NF-1) }'