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.1
,test.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