-1

例如,假设我们有以下一行:

RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail

这里test、slave、owners、time和status是不同的属性。属性的数量可能会有所不同,即,可以存在像 category=xyz 这样的另一个属性,或者可能不存在某些属性。

我正在寻找一个匹配的正则表达式,如果“owners=”包含特定的所有者,比如“own2”。此外,此正则表达式不应与该行中的其他匹配项匹配。例如行可以是:

RESULT: test=own2 slave=def owners=own1,test,own2,newown time=32 status=fail

正则表达式不应匹配 own2 的“test”属性。

我花了几个小时搜索但失败了:(

我用 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 等。

编辑 - 现在举例

非常感谢您的回复!

让我用更清晰的例子来解释:

我的文件内容:

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”行将失败。

因此,我需要一个正则表达式,它仅在模式出现在“所有者”列表中的任何位置时才匹配。

注意:如果“所有者”列表有多个所有者,则以逗号分隔。否则,它只有一个值。例如:所有者=abc

希望我的问题现在更清楚了。

4

6 回答 6

1

纯 bash 解决方案:

line='RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail'

declare -A allValues
while read -r -d ' ' curValue; do
    IFS='=' read key value <<< "${curValue}"
    allValues["$key"]=$value
done <<< "${line#RESULT: } "

这创建了一个很好的关联数组。现在很容易得到任何值:

echo "${allValues[slave]}" # prints 'def'
echo "${allValues[owners]}" # prints 'own1,test,own2,newown'

现在,要查看是否own2真的存在,您可以使用=~

if [[ ${allValues[owners]} =~ own2 ]]; then

或使用 glob:

if [[ ${allValues[owners]} = *own2* ]]; then

编辑:

哎呀!

想象这样的数据:owners=own1,test,thisown2iswrong,newown
以前的两种解决方案都将返回true,这可能不是您想要的。
这是一个更好的正则表达式:

if [[ ${allValues[owners]} =~ (^|,)own2(,|$) ]]; then
于 2013-09-05T14:06:50.280 回答
1

你可以使用这个:

echo "$line" | grep -E '\<owners=([[:alnum:]]+,)*own2($|[, ])'

这将找到包含 owner 值的任何字符串,其中包含 own2 的逗号分隔值

于 2013-09-05T14:02:11.880 回答
1

给定文件

$ cat file
RESULT: test=abc slave=def owners=own1,test,own2,newown time=32 status=fail

此 grep 表达式仅显示 之后的内容owners=

$ grep -Po '(?<=owners=)\w+' file
own1

如果文件包含更多信息无关紧要:

$ cat file
RESULT: test=abc slave=def owners=own1,hello=3,test,own2,newown time=32 status=fail, more things
$ grep -Po '(?<=owners=)\w+' file
own1

使用此文本,您可以继续处理if条件:

if [[ "$(grep -Po '(?<=owners=)\w+' file)" == *own1* ]]; then
   echo "it is there"
fi

测试:

$ if [[ "$(grep -Po '(?<=owners=)\w+' file)" == *own1* ]]; then echo "it is there"; fi
it is there
于 2013-09-05T13:56:59.160 回答
0

干得好。该脚本需要 GNU Awk (gawk)。

#!/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

运行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
--------------------

代码应该很容易根据您自己的要求进行定制。只要问我你是否需要帮助。

于 2013-09-05T22:27:04.827 回答
0

非常感谢您的见解和回答。

以下产生了结果:

grep RESULT myfile | grep "pass" | egrep \(\(owners=\)*\(grp1\)\|\(owners=\)*\(grp2\)\)

由此我理解的是

1)当您有多个模式时,将它们括在括号中

2)如果有多个这样的模式,它们应该用管道分隔,并且应该有另一个括号覆盖所有模式

如果只有一种这样的模式,则覆盖括号是可选的。这适用于我测试的所有平台,即 AIX、HPUX、LINUX、SOLARIS 和 NT。

于 2013-09-13T18:15:30.197 回答
0

你试过了吗:

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)

于 2013-09-05T13:57:52.247 回答