Bash Shell脚本-匹配特定命名字段中的值
例如,假设我们有一行:Bash Shell脚本-匹配特定命名字段中的值,bash,shell,unix,Bash,Shell,Unix,例如,假设我们有一行: RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail 在这里,测试、从属、所有者、时间和状态是不同的属性。 属性的数量可能会有所不同,例如,可能存在另一个属性,如category=xyz,或者某些属性可能不存在 我正在寻找一个正则表达式,如果“owner=”包含一个特定的所有者,比如“own2”,则该正则表达式匹配。此外,此正则表达式不应与行中的其他引用相匹配。例如,行可以
RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail
在这里,测试、从属、所有者、时间和状态是不同的属性。
属性的数量可能会有所不同,例如,可能存在另一个属性,如category=xyz,或者某些属性可能不存在
我正在寻找一个正则表达式,如果“owner=”包含一个特定的所有者,比如“own2”,则该正则表达式匹配。此外,此正则表达式不应与行中的其他引用相匹配。例如,行可以是:
RESULT: test=own2 slave=def owners=own1,test,own2,newown time=32 status=fail
正则表达式不应与“test”属性的own2匹配
我花了几个小时搜索,但失败了:(
我使用egrep查找正则表达式。我尝试了以下方法:
line="RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail"
echo $line | egrep "owners=*own2*"
这无法返回任何值。我不知道正则表达式有什么问题
我正在寻找能够在所有Unix版本上工作的东西,如Linux、AIX、Solaris等
编辑-现在使用示例
非常感谢您的回复 让我用更清楚的例子来解释: myfile的内容:
blabla
blaaaaaa some text
RESULT: test=abcgrp1 slave=def owners=test,own2,newown time=32 status=fail
some more blabla
xyze
RESULT: test=abc1 slave=def owners=grp1,test time=32 status=pass
some text here
RESULT: test=abc2 slave=def owners=gr,grp1 time=32 status=pass
我想获得状态为“通过”且“所有者”为“grp1”或“grp2”的测试因此,最初,我写道:
grep RESULT myfile | grep "pass" | egrep "grp1|gpr2"
没花多少时间就意识到这是不正确的,因为它在“myfile”中的第一行“RESULT”返回true
所以,我想这样写:
grep RESULT myfile | grep "pass" | egrep "owners=grp1|owners=gpr2"
显然,对于“myfile”中的第三行“RESULT”,这将失败
因此,我需要一个正则表达式,它只在模式出现在“所有者”列表中的任何位置时匹配
注意:“所有者”列表如果有多个所有者,则以逗号分隔。否则,它只有一个值。例如:owners=abc
希望我的问题现在更清楚。给定文件
$ cat file
RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail
此grep表达式仅显示所有者=
之后的内容:
$ grep -Po '(?<=owners=)\w+' file
own1
测试:
$if[[”$(grep-Po'(?您是否尝试过:
echo "RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail" | grep "owners=[^ ]*own2"
例如:
$ echo "RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail" | grep -Po "owners=\K[^ ]*own[0-9]"
own1,test,own2
你也许想说:
echo $line | egrep "owners=.*own2.*"
(注意模式中额外的
s)您可以使用:
echo "$line" | grep -E '\<owners=([[:alnum:]]+,)*own2($|[, ])'
echo“$line”| grep-E'\Pure bash解决方案:
现在,要查看是否确实存在own2
,您可以使用=~
:
if [[ ${allValues[owners]} =~ own2 ]]; then
或使用globs:
if [[ ${allValues[owners]} = *own2* ]]; then
编辑:
哎呀
想象这样的数据:owners=own1,test,thisown2swrong,newown
前面的两个解决方案都将返回true
,这可能不是您想要的结果。
下面是一个更好的regexp:
if [[ ${allValues[owners]} =~ (^|,)own2(,|$) ]]; then
给你。这个脚本需要GNUawk(gawk)
运行gawk-f script.awk sample.txt
将给出:
--------------------
some more blabla
xyze
RESULT: test=abc1 slave=def owners=grp1,test time=32 status=pass
--------------------
--------------------
some text here
RESULT: test=abc2 slave=def owners=gr,grp1 time=32 status=pass
--------------------
--------------------
some more blabla
xyze
RESULT: test=abc1 slave=def owners=grp1,test time=32 status=pass
--------------------
代码应该可以根据您自己的要求轻松定制。如果需要帮助,请咨询我。非常感谢您的见解和回答
结果如下:
grep RESULT myfile | grep "pass" | egrep \(\(owners=\)*\(grp1\)\|\(owners=\)*\(grp2\)\)
从这里我了解到的是
1) 如果有多个图案,请将它们括在括号中
2) 如果有多个这样的模式,它们应该用管道隔开,并且应该有另一个括号覆盖所有模式
如果只有一个这样的模式,则括号是可选的。这在我测试的所有平台上都有效,即AIX、HPUX、LINUX、SOLARIS和NT。据我所知,OP希望检查所有者值是否包含一些字符串。而不是提取值shi@Kent。是的,我用正确的答案更新:)希望现在更清楚。你似乎对正则表达式和文件名通配符之间的区别感到困惑。即使你使用了正则表达式*own2.*
,这个正则表达式可能适用于给定的示例。但它不可靠。如果有userown21、own22、own222、fooown2…
我想你明白我的意思了。如果你愿意的话与大多数Shell兼容我不认为这应该被标记为bash
。此外,根据您对文本的处理方式,我认为如果您使用Awk会更好。如果您提供更多详细信息,例如,您如何使用命令获取行,以及您计划如何处理在这些行上找到的键/值,我们可以提供更多帮助nes.@konsolebox谢谢,在帖子中添加了更多的细节!这将匹配owners=fred,barney status=小丑24
。呃,我认为已经处理好了(参见前两个示例)无论如何,你仍然在点击owners=小丑24
。在这些答案中,这是最接近理智的解决方案,但它需要锚定和正确的引用。echo“$line”
用双引号,egrep'\n你想要egrep”owners=([:alnum:*,)*own2(,[:alnum:*)*"
@tripleee如果您认为答案很接近,但包含一些错误,您可以随时编辑其他人的答案,谢谢您升级解决方案,但我还是将您的回答视为继续进行的邀请。显然,如果出现沟通错误,请随时回滚。@tripleee哦,我不知道,谢谢。再次感谢您升级了我的answar。
if [[ ${allValues[owners]} =~ own2 ]]; then
if [[ ${allValues[owners]} = *own2* ]]; then
if [[ ${allValues[owners]} =~ (^|,)own2(,|$) ]]; then
#!/usr/bin/gawk -f
function parse_file(file, a, count, id, key, text, values) {
FS = " "
id = 0
while ((getline < file) > 0) {
if (!/^[[:blank:]]*$/) {
text = ""
do {
if (/^RESULT: /) {
tests[id] = text
tests_results[id] = $0
count = split($0, props)
for (i = 2; i <= count; ++i) {
match(props[i], /([^=]+)=?(.*)/, a)
key = a[1]; values = a[2]
if (length(tests_props[id])) {
tests_props[id] = tests_props[id] "|" key
} else {
tests_props[id] = key
}
tests_props[id "|" key] = values
}
break
} else {
if (length(text)) {
text = text "\n" $0
} else {
text = $0
}
}
} while ((getline < file) > 0)
++id
}
}
tests_count = id
}
function get_values(id, key, var, a, i, t, v) {
v = tests_props[id "|" key]
split(v, a, /,/)
delete var
for (i = 1; i in a; ++i) {
t = a[i]
var[t] = t
}
}
function print_test(id) {
print "--------------------"
print tests[id]
print tests_results[id]
print "--------------------"
}
BEGIN {
parse_file(ARGV[1])
for (i in tests) {
get_values(i, "owners", owners)
get_values(i, "status", status)
if (("grp1" in owners || "grp2" in owners) && "pass" in status) {
print_test(i)
}
}
exit
}
blabla
blaaaaaa some text
RESULT: test=abcgrp1 slave=def owners=test,own2,newown time=32 status=fail
some more blabla
xyze
RESULT: test=abc1 slave=def owners=grp1,test time=32 status=pass
some text here
RESULT: test=abc2 slave=def owners=gr,grp1 time=32 status=pass
some more blabla
xyze
RESULT: test=abc1 slave=def owners=grp1,test time=32 status=pass
--------------------
some more blabla
xyze
RESULT: test=abc1 slave=def owners=grp1,test time=32 status=pass
--------------------
--------------------
some text here
RESULT: test=abc2 slave=def owners=gr,grp1 time=32 status=pass
--------------------
--------------------
some more blabla
xyze
RESULT: test=abc1 slave=def owners=grp1,test time=32 status=pass
--------------------
grep RESULT myfile | grep "pass" | egrep \(\(owners=\)*\(grp1\)\|\(owners=\)*\(grp2\)\)