grep/awk 用于匹配两个字符串

grep/awk 用于匹配两个字符串

我需要使用仅当服务状态命令输出中出现“已加载”和“正在运行”时才为 true 的 if 语句:

$groupservice status
service 1 is loaded
service 2 is running 

正如前面提到的,我曾尝试使用它:

$service status | awk '/is loaded/ && /is running/'

但我没有得到任何输出。运行它的唯一方法是这样:

if [[ $(service status | grep "is loaded") ]]  && [[ $(service status | grep "is running") ]]

但我更喜欢使用更短的表达方式。我哪里错了?谢谢

答案1

awk您可以通过计算匹配次数来完成此操作:

$ service status | 
    awk '/is loaded/{l++} 
         /is running/{r++} 
        (l && r){
            print "found"; 
            exit 0
        }
        END{
          if  (!(l && r)){
            print "not found"; 
            exit 1
            }
        }'

我能想到的唯一方法grep是对grep文件执行两次。像这样的东西:

service status | 
    grep -qF 'is loaded' && foo.sh | 
        grep -qF 'is running' && 
            echo Found || 
                echo "not found"

当然,这有一个竞争条件,如果service两次调用之间的输出发生变化,您可能会得到不正确的结果。为了解决这个问题,您可以使用 tmp 文件:

service status > /tmp/file
grep -qF 'is loaded'  /tmp/file &&
    grep -qF 'is running' /tmp/file &&
        echo Found || 
            echo "not found"

答案2

假设,就像在您发布的示例输入中一样,输出中没有空行,service status然后使用任何 awk:

if service status | awk -v RS= '/is loaded/ && /is running/{f=1} END{exit !f}'; then
    echo "Eureka!"
fi
Eureka!

显然,如果您需要做的只是打印一些内容,那么您不需要 shellif语句或提供 awk 的退出状态:

service status | awk -v RS= '/is loaded/ && /is running/{print "Eureka!"}'
Eureka!

如果有空行并且您有 GNU awk,则只需更改RS=RS='^$'.

相关内容