我怎样才能从通过管道传输的同一输入中查找两个值?

我怎样才能从通过管道传输的同一输入中查找两个值?

CentOS 5.x

我正在尝试构建一个 shell 脚本来搜索通过 stdin 提供的数据。以下是输入流的示例:

Date: 1/1/11 
Time: 12:00 AM 
Foo: 12345 
Foo1: dskjflsdkjflksdjlfds 
Foo2: 123456789 
Foo3: kdsjflskdjflkjsdlkfjsdlkjflksdjflkjsdklfjlksdjflk

该信息不存在于文件中,它只会作为另一个应用程序的标准输出实时发送到脚本。

我希望脚本查看数据并解析出Foo:Foo2:将它们存储为变量以供稍后在脚本中使用。

我修改后的脚本尝试如下:

#!/bin/bash
while read data; do
        SearchCriteria1=$(echo "$data" | grep "Foo: " | cut -c 5-)
        SearchCriteria2=$(echo "$data" | grep "Foo2: " | cut -c 6-)
        echo $SearchCriteria1 >> test.1
        echo $SearchCriteria2 >> test.2
done

完成的脚本实际上不会使用 test.1 或 test 2 文件。我只是为了方便举例而在这里列出它们。

在这个例子中,我希望 test.1 具有:

12345

在这个例子中,我希望 test.2 具有:

123456789

但是,当我测试这个时,test.1 和 test.2 都是空白的,我知道数据中包含有效信息。

我忽略了一些显而易见的事情。有人能解释一下吗?

答案1

想想你的 greps 从哪里获取输入。你没有给它们输入文件名,所以它们从标准输入读取。它们的标准输入是什么?没有重定向,也没有管道进入 greps,所以它们使用循环继承的标准输入运行。

read执行一次。它将第一行读入$data,而您从未在任何地方使用过(这应该是有问题的线索)。然后第一个 grep 运行,它消耗所有输入,第二个 grep 附加到相同的输入,因此它会立即获得 EOF。

这可能更接近你想要的:

SearchCriteria1=$(echo "$data" | grep "Foo " | cut -c 10-)
SearchCriteria2=$(echo "$data" | grep "Foo2 " | cut -c 13-)

末尾的分号毫无用处所以我把它们去掉了。

您可能还希望附加到test.1test.2否则循环中的每次迭代都会覆盖前一次写入的内容。

从总体上看,您似乎想要一个“多输出 grep”。您的 read 循环对每行进行单独的 grep 是一种实现方法,但效率不高。最近在以下网址讨论了其他一些方法https://stackoverflow.com/questions/11676350/grepping-a-20g-file-in-bash/11676853

答案2

input stream producer |
egrep 'Foo:|Foo2:' |
while read foo data
do
        case $foo in
                Foo:) echo "do something with $foo -- $data" ;;
                Foo2:) echo "do something else with $foo -- $data" ;;
        esac
done

egrep行不是必需的,但可以减少循环中不必要的输入。然后分为两个变量(数据)并使用案件在它们之间做出选择并采取相应行动(你可以在这个阶段分配数据如果愿意的话,还可以将其转换为另一个变量)。

答案3

这个怎么样:

$ ./another.app | awk '/Foo: / { print $2 }' > test.1
$ ./another.app | awk '/Foo2: / { print $2 }' > test.2

相关内容