bash grep,否则打印不匹配的消息
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26371440/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
grep, else print message for no matches
提问by seraththundhuil
In a bash script, I have a list of lines in a file I wish to grep and then display on standard out, which is easiest done with a while read:
在 bash 脚本中,我有一个文件中的行列表,我希望 grep 然后在标准输出上显示,这是最简单的一段时间阅读:
grep "regex" "filepath" | while read line; do
printf "$line\n"
done
However, I would like to inform the user if no lines were matched by the grep. I know that one can do this by updating a variable inside the loopbut it seems like a much more elegant approach (if possible) would be to try to read a line in an until loop, and if there were no output, an error message could be displayed.
但是,如果grep 没有匹配任何行,我想通知用户。我知道可以通过更新循环内的变量来做到这一点,但似乎更优雅的方法(如果可能)是尝试读取直到循环中的一行,如果没有输出,则会显示错误消息可以显示。
This was my first attempt:
这是我的第一次尝试:
grep "regex" "filepath" | until [[ -z ${read line} ]]; do
if [[ -z $input ]]; then
printf "No matches found\n"
break
fi
printf "$line\n"
done
But in this instance the read command is malformed, and I wasn't sure of another way the phrase the query. Is this approach possible, and if not, is there a more suitable solution to the problem?
但是在这种情况下,读取命令格式错误,我不确定查询语句的另一种方式。这种方法是否可行,如果不可行,是否有更合适的解决方案?
回答by John Kugelman
You don't need a loop at all if you simply want to display a message when there's no match. Instead you can use grep's return code. A simple if
statement will suffice:
如果您只是想在没有匹配项时显示消息,则根本不需要循环。相反,您可以使用 grep 的返回码。一个简单的if
语句就足够了:
if ! grep "regex" "filepath"; then
echo "no match" >&2
fi
This will display the results of grep matches (since that's grep's default behavior), and will display the error message if it doesn't.
这将显示 grep 匹配的结果(因为这是 grep 的默认行为),如果没有,将显示错误消息。
A popular alternative to if !
is to use the ||
operator. foo || bar
can be read as "do foo
or else do bar
", or "if not foo
then bar
".
一种流行的替代方法if !
是使用||
运算符。foo || bar
可以读作“do foo
or else do bar
”,或者“if not foo
then bar
”。
grep "regex" "filepath" || echo "no match" >&2
回答by tripleee
John Kugelman's answer is the correct and succinct one and you should accept it. I am addressing your question about syntax here just for completeness.
John Kugelman 的回答是正确而简洁的,您应该接受它。我在这里解决您关于语法的问题只是为了完整性。
You cannot use ${read line}
to execute read
-- the brace syntax actually means (vaguely) that you want the value of a variable whose name contains a space. Perhaps you were shooting for $(read line)
but really, the proper way to write your until
loop would be more along the lines of
你不能${read line}
用来执行read
——大括号语法实际上意味着(模糊地)你想要一个名称包含空格的变量的值。也许你是为了$(read line)
但实际上,编写until
循环的正确方法更像是
grep "regex" "filepath" | until read line; [[ -z "$line" ]]; do
... but of course, when there is no output, the pipeline will receive no lines, so while
and until
are both wrong here.
...但是当然,当没有输出时,管道将不会收到任何行,因此while
和until
在这里都是错误的。
It is worth amphasizing that the reason you need a separate do
is that you can have multiple commands in there. Even something like
值得强调的是,您需要一个单独的原因do
是您可以在其中拥有多个命令。甚至像
while output=$(grep "regex filepath"); echo "grep done, please wait ...";
count=$(echo "$output" | wc -l); [[ $count -gt 0 ]]
do ...
although again, that is much more arcane than you would ever really need. (And in this particular case, you would want probably actually want if
, not while
.)
尽管如此,这比您真正需要的要神秘得多。(在这种特殊情况下,您可能实际上想要的是if
,而不是while
。)
As others already noted, there is no reason to use a loop like that here, but I wanted to sort out the question about how to write a loop like this for whenever you actually do want one.
正如其他人已经指出的那样,没有理由在这里使用这样的循环,但我想解决有关如何在您真正想要循环时编写这样的循环的问题。
回答by Six
As mentioned by @jordanm, there is no need for a loop in the use case you mentioned.
正如@jordanm 所提到的,在您提到的用例中不需要循环。
output=$(grep "regex" "file")
if [[ -n $output ]]; then
echo "$output"
else
echo "Sorry, no results..."
fi
If you need to iterate over the results for processing (rather than just displaying to stdout) then you can do something like this:
如果您需要迭代处理结果(而不仅仅是显示到标准输出),那么您可以执行以下操作:
output=$(grep "regex" "file")
if [[ -n $output ]]; then
while IFS= read -r line; do
# do something with $line
done <<< "$output"
else
echo "Sorry, no results..."
fi
This method avoids using a pipeline or subshell so that any variable assignments made within the loop will be available to the rest of the script.
此方法避免使用管道或子外壳,以便在循环内进行的任何变量分配都可用于脚本的其余部分。
Also, i'm not sure if this relates to what you are trying to do at all, but grep does have the ability to load patterns from a file (one per line). It is invoked as follows:
另外,我不确定这是否与您要执行的操作有关,但是 grep 确实能够从文件(每行一个)加载模式。它的调用方式如下:
grep search_target -f pattern_file.txt