我需要从文件中获取特定的版本字符串(称之为version.lst)并使用它来比较shell脚本中的另一个。例如,文件包含如下所示的行:
V1.000 -- build date and other info here -- APP1
V1.000 -- build date and other info here -- APP2
V1.500 -- build date and other info here -- APP3
..等等。假设我试图从APP1获取第一个版本(在本例中为V1.000)。显然,版本可以改变,我希望它是动态的。我现在所做的工作:
var = `cat version.lst | grep " -- APP1" | grep -Eo V[0-9].[0-9]{3}`
管道到grep将获得包含APP1的行,第二个管道到grep将获得版本字符串。但是,我听说grep不是这样做的,所以我想学习使用awk或sed的最佳方法。有任何想法吗?我是两个新手,并没有找到足够简单的教程来学习它的语法。他们支持egrep吗?谢谢!
答案 0 :(得分:11)
试试这个以获得完整版本:
#!/bin/sh
app=APP1
var=$(awk -v "app=$app" '$NF == app {print $1}' version.lst)
或仅获取主要版本号,最后一行可以是:
var=$(awk -v "app=$app" '$NF == app {split($1,a,"."); print a[1]}' version.lst)
使用sed
获取完整版本:
var=$(sed -n "/ $app\$/s/^\([^ ]*\).*/\1/p" version.lst)
或者这只得到主版本号:
var=$(sed -n "/ $app\$/s/^\([^.]*\).*/\1/p" version.lst)
说明:
第二个AWK命令:
-v "app=$app"
- 设置一个等于shell变量的AWK变量$NF == app
- 如果最后一个字段等于变量的内容(NF
是字段数,那么$NF
是第N个字段的内容){split($1,a,".")
- 然后在点print a[1]
- 并打印拆分结果的第一部分 sed
命令:
-n
- 除非指示"/ $app\$/
- 对于以(\$
)结尾的任何行,shell变量$app
的内容(不是双引号用于允许变量扩展而且它是一个逃离第二个美元符号的好主意)s/^\([^ ]*\).*/\1/p"
- 从该行的开头(^
)开始,捕获\(\)
由非空格([^ ]
)组成的字符序列(或非任何数字(零或更多*
)并且匹配但不捕获该行(.*
)上的所有其余字符的第二个版本中的字段),替换匹配的文本(在这种情况下的整行)与捕获的字符串(版本号)(\1
引用第一个(在这种情况下)仅捕获组,并打印它(p
)答案 1 :(得分:3)
如果我理解正确:egrep "APP1$" version.lst | awk '{print $1}'
答案 2 :(得分:1)
$ awk '/^V1\.00.* APP1$/{print $NF}' version.lst
APP1
该正则表达式匹配以“V1.00”开头的行,后跟任意数量的任何其他字符,以“APP1”结尾。中间的反斜杠可能非常重要 - 它只匹配“。”,因此它排除(可能是腐败的)可能以“V1a00”开头的行。 “APP1”之前的空格不包括“APP2_APP1”之类的内容。
“NF”是一个自动生成的变量,包含输入行中的字段数。它也是最后一个字段的编号,恰好是您感兴趣的字段。
有几种方法可以修剪“V1”。这是一种方式,虽然你和我可能不会谈论完全相同的事情。
$ awk '/^V1\.00.* APP1$/{print substr($1, 1, index($1, ".") - 1), $NF}' version.lst
V1 APP1