I have a script that outputs about 10 lines every time if it run. The content of these lines varies.
我有一个脚本,每次运行时输出大约10行。这些线条的内容各不相同。
I would really like to be able to grep
in the output and do different things depending on the output.
我非常希望能够在输出中加入grep,并根据输出来做不同的事情。
In pseudo this is what I would like to do
在pseudo中,我想这样做
cat /etc/password | \\
if [ grep "root" $STDOUT ]; then
echo "root is found"
elif [ grep "nobody" $STDOUT ]; then
echo "nobody is found"
fi
Here have I used cat /etc/password
as an example, but it should be replaced with my scripts mentioned above.
这里我使用了cat /etc/password作为示例,但是应该用上面提到的脚本替换它。
The problem is, how do I get hold of the output from cat /etc/password
in the if
/elif
conditions?
问题是,如何在if/elif条件下获得cat /etc/password的输出?
7 个解决方案
#1
6
As @Benoit recommends, just use grep
directly.
正如@Benoit所建议的,只需直接使用grep。
As @larsmans notes, you can avoid a double-read of the file by reading it into a variable once.
正如@larsmans指出的,您可以通过一次将文件读入变量来避免重复读取。
Given the availability of bash
I'd do it like this:
考虑到bash的可用性,我将这样做:
password=$(< /etc/passwd)
if grep -q root <<< "$password" ; then
echo root found
elif grep -q nobody <<< "$password" ; then
echo nobody found
fi
One read of the file, one or two invocations of grep
, no other processes or subshells launched.
一次读取文件,一次或两次调用grep,没有启动其他进程或子shell。
#2
3
You just do :
你做的事:
if grep -q "root" /etc/passwd ; then
...
fi
which will play the ...
commands if grep exit code is 0.
会播放…如果grep退出代码为0,则命令。
remember that \[
is a external command, probably located in /usr/bin/[
(normally it's a hard link to test
and when invoked as [
it requires a matching ]
argument). Also see the pitfalls page here, many of them deal are related to that command.
记住,\[是一个外部命令,可能位于/usr/bin/[(通常它是一个要测试的硬链接,当调用时,它需要一个匹配的参数)。还可以在这里看到缺陷页面,其中许多与该命令相关。
#3
3
I'd suggest using awk:
我建议使用awk:
cat /etc/passwd | awk '/root/{ do something }/nobody/{ do something else }'
You can achieve the same in bash using an expression like:
您可以在bash中使用如下表达式来实现相同的结果:
cat /etc/passwd |
while read; do
if echo "$REPLY" | fgrep root; then
something
fi
if echo "$REPLY" | fgrep nobody; then
something_else
fi
done
However the pure bash solution is less efficient for large inputs because it runs separate instances of grep
for every line.
但是,对于大型输入,纯bash解决方案效率较低,因为它对每一行运行grep的单独实例。
#4
1
Piping into an if-statement is possible with subshells, but that solution will break since you're running two grep
commands on the pipe, the first of which will exhaust it.
对于子shell,管道进入if语句是可能的,但是由于您在管道上运行两个grep命令,第一个命令将耗尽该解决方案。
The best solution in your case is probably to read /etc/passwd
into a variable, then grep
it:
在您的示例中,最好的解决方案可能是将/etc/passwd转换为一个变量,然后grep:
passwd=$(cat /etc/passwd)
if (echo $passwd | grep -q root); then
echo "root found"
fi
if (echo $passwd | grep -q nobody); then
echo "nobody found"
fi
#5
1
Just use &&:
只使用& &:
grep -q root /etc/password && echo "root is found"
grep -q nobody /etc/password && echo "nobody is found"
#6
0
In the general case, you could use a temporary file.
在一般情况下,可以使用临时文件。
t=$(mktemp -t passwd.XXXXXXXX)
trap 'rm $t' 0
trap 'exit 127' 1 2 3 5 15
cat >$t
for u in root nobody; do
fgrep $u $t
done
The trap
s are to remove the temporary file afterwards.
这些陷阱将在之后移除临时文件。
As an aside, you can pipe to an if
, but the first grep
inside your conditional would already consume all of its standard input. It's more useful in situations like this:
顺便说一句,您可以将管道传输到if,但是条件语句中的第一个grepin已经消耗了它的所有标准输入。在这种情况下它更有用:
if $option_count ; then
wc -l
else
tac
fi <file
#7
0
How about the following:
如何:
#!/bin/bash
if [ -z $1 ]; then
echo Usage: $0 [UID to search for]
exit 1;
fi
SEARCHID="$1"
function notFound() {
echo NOT FOUND
}
function found() {
echo Found it
}
function main() {
grep -i $SEARCHID /etc/passwd
# Move $? to a variable
SEARCHRESULT=$?
if [ "$SEARCHRESULT" != "0" ]; then
notFound;
else
found;
fi
}
# call main function
main
#1
6
As @Benoit recommends, just use grep
directly.
正如@Benoit所建议的,只需直接使用grep。
As @larsmans notes, you can avoid a double-read of the file by reading it into a variable once.
正如@larsmans指出的,您可以通过一次将文件读入变量来避免重复读取。
Given the availability of bash
I'd do it like this:
考虑到bash的可用性,我将这样做:
password=$(< /etc/passwd)
if grep -q root <<< "$password" ; then
echo root found
elif grep -q nobody <<< "$password" ; then
echo nobody found
fi
One read of the file, one or two invocations of grep
, no other processes or subshells launched.
一次读取文件,一次或两次调用grep,没有启动其他进程或子shell。
#2
3
You just do :
你做的事:
if grep -q "root" /etc/passwd ; then
...
fi
which will play the ...
commands if grep exit code is 0.
会播放…如果grep退出代码为0,则命令。
remember that \[
is a external command, probably located in /usr/bin/[
(normally it's a hard link to test
and when invoked as [
it requires a matching ]
argument). Also see the pitfalls page here, many of them deal are related to that command.
记住,\[是一个外部命令,可能位于/usr/bin/[(通常它是一个要测试的硬链接,当调用时,它需要一个匹配的参数)。还可以在这里看到缺陷页面,其中许多与该命令相关。
#3
3
I'd suggest using awk:
我建议使用awk:
cat /etc/passwd | awk '/root/{ do something }/nobody/{ do something else }'
You can achieve the same in bash using an expression like:
您可以在bash中使用如下表达式来实现相同的结果:
cat /etc/passwd |
while read; do
if echo "$REPLY" | fgrep root; then
something
fi
if echo "$REPLY" | fgrep nobody; then
something_else
fi
done
However the pure bash solution is less efficient for large inputs because it runs separate instances of grep
for every line.
但是,对于大型输入,纯bash解决方案效率较低,因为它对每一行运行grep的单独实例。
#4
1
Piping into an if-statement is possible with subshells, but that solution will break since you're running two grep
commands on the pipe, the first of which will exhaust it.
对于子shell,管道进入if语句是可能的,但是由于您在管道上运行两个grep命令,第一个命令将耗尽该解决方案。
The best solution in your case is probably to read /etc/passwd
into a variable, then grep
it:
在您的示例中,最好的解决方案可能是将/etc/passwd转换为一个变量,然后grep:
passwd=$(cat /etc/passwd)
if (echo $passwd | grep -q root); then
echo "root found"
fi
if (echo $passwd | grep -q nobody); then
echo "nobody found"
fi
#5
1
Just use &&:
只使用& &:
grep -q root /etc/password && echo "root is found"
grep -q nobody /etc/password && echo "nobody is found"
#6
0
In the general case, you could use a temporary file.
在一般情况下,可以使用临时文件。
t=$(mktemp -t passwd.XXXXXXXX)
trap 'rm $t' 0
trap 'exit 127' 1 2 3 5 15
cat >$t
for u in root nobody; do
fgrep $u $t
done
The trap
s are to remove the temporary file afterwards.
这些陷阱将在之后移除临时文件。
As an aside, you can pipe to an if
, but the first grep
inside your conditional would already consume all of its standard input. It's more useful in situations like this:
顺便说一句,您可以将管道传输到if,但是条件语句中的第一个grepin已经消耗了它的所有标准输入。在这种情况下它更有用:
if $option_count ; then
wc -l
else
tac
fi <file
#7
0
How about the following:
如何:
#!/bin/bash
if [ -z $1 ]; then
echo Usage: $0 [UID to search for]
exit 1;
fi
SEARCHID="$1"
function notFound() {
echo NOT FOUND
}
function found() {
echo Found it
}
function main() {
grep -i $SEARCHID /etc/passwd
# Move $? to a variable
SEARCHRESULT=$?
if [ "$SEARCHRESULT" != "0" ]; then
notFound;
else
found;
fi
}
# call main function
main