[英]How to search for “ERROR” string from the output of the test in shell scripting?
我正在修改一个shell脚本,该脚本使用Makefile在不同的测试台上测试代码,当前该shell脚本仅回显SUCCESS和FAILURE,我想修改此shell脚本以搜索正在写入到另一个文件的输出跟踪字符串。在同一位置调用Makefile,即trace.log。 如果它找到单词“ ERROR”(这是一个跟踪字符串),我希望测试说失败
!/usr/bin/env bash
#set -e
BASEDIR=$(pwd)
REPOROOT=`git rev-parse --show-toplevel`
RED="`tput setaf 1`"
GREEN="`tput setaf 2`"
BLUE="`tput setaf 4`"
NORM="`tput sgr0`"
Test() {
pushd ${REPOROOT}/rr/Fmda/body > /dev/null
tests=`find . -type f | grep "test.xml" | sed "s/test\.xml//"`
for t in $tests; do
testname=`echo $t | sed "s/\.\///" | sed "s/\/test\///"`
echo -e "${BLUE}EXECUTING $testname TEST${NORM}"
pushd $t > /dev/null
make test_svp
if [ $? -eq 0 ]; then
echo -e "${GREEN}SUCCESS IN $testname TEST MOVING ON!${NORM}"
else
echo "${RED}FAILURE IN $testname TEST${NORM}"
exit 1
fi
popd > /dev/null
done
popd > /dev/null
}
我没有shell脚本方面的背景。 我通过搜索构造了解了这里写的内容,但我仍然不了解for t in $tests
工作方式以及sed
作用。
我认为可以解决我的问题的是
error=trace.log|grep "ERROR"
if [ $? -eq 0] && [ !error ]; then
研究了一下$?
和Shell脚本编写,我知道这行不通,我应该怎么做才能实现这一目标?
for variable in one two three
的for
循环for variable in one two three
将在循环的主体中运行,将$variable
设置为在第一次迭代中设置为one
,在第二次迭代中设置为two
,然后设置为three
。 循环完成后,变量将保留其在循环中拥有的最后一个值。
sed
本身就是一种脚本语言,尽管通常它仅用于琐碎的字符串替换。 sed
脚本s/regex/replacement/g
将用其处理文件中的静态字符串replacement
正则表达式上的所有匹配项。 (在没有/g
标志的情况下,将仅替换每个输入行上的第一个匹配项。)
通常,脚本应该检查命令的退出状态,而不是人类可读字符串的grep。 make
命令已经说明了这一点,尽管它并不完全是惯用的。
顺便说一句,第一行的shebang必须以两个字符#!
开头#!
这是带有注释的重构。
#!/usr/bin/env bash
#set -e
# Use lower case for your private variables
# BASEDIR was never used for anything
# Consistently use modern command substitution syntax
reporoot=$(git rev-parse --show-toplevel)
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
BLUE="$(tput setaf 4)"
NORM="$(tput sgr0)"
Test() {
# Maybe don't pushd; see below
# Quote the variable properly
pushd "$reporoot/rr/Fmda/body" > /dev/null
# Refactor to avoid useless use of grep
tests=$(find . -type f | sed -n "s/test\.xml//p")
for t in $tests; do
# Proper quoting; refactor to a single sed script
# Fix sed syntax error (too many slashes)
testname=$(echo "$t" | sed "s/\.\//;s%/test/%%")
echo -e "${BLUE}EXECUTING $testname TEST${NORM}"
pushd "$t" > /dev/null
# Use "if" like it was meant to
# Add grep condition
if make test_svp && ! grep -q "ERROR" trace.log; then
echo -e "${GREEN}SUCCESS IN $testname TEST MOVING ON!${NORM}"
else
echo "${RED}FAILURE IN $testname TEST${NORM}"
exit 1
fi
popd >/dev/null
done
popd >/dev/null
}
请注意在make
之后添加了grep
。 &&
说“和”,然后说!
反转grep
的退出代码(因此,如果grep
找不到任何匹配项,则为true)。 -q
抑制grep
输出的匹配项,并使其在找到第一个匹配项后立即停止搜索。
更切地讲,我认为pushd
和popd
用于交互用途。 Shell脚本通常只是在子Shell中使用cd
,然后在子Shell完成后,您便回到了开始的目录中。 但是在这里,可能需要更基本的重构。
对于稍微复杂但希望强大的重构,也许可以
Test() {
find "$reporoot/rr/Fmda/body" -name 'test.xml' \
\( -execdir sh -c '
# XXX TODO: maybe replace with parameter substitutions
testname=$(echo "$1" | sed "s%/test\.xml$%%;s/\.\//;s%/test/%%")
echo -e "${BLUE}EXECUTING $testname TEST${NORM}"
make test_svp &&
! grep -q "ERROR" trace.log &&
echo -e "${GREEN}SUCCESS IN $testname TEST MOVING ON!${NORM}" ||
{
echo "${RED}FAILURE IN $testname TEST${NORM}"
exit 1; }' _ {} \; -o -quit \)
}
... -quit
谓词在很大程度上是GNU find
扩展(stol ...从这里受宠若惊)。
关于测试文件名的一些假设可能不正确。 test.xml
是测试的实际文件名,还是只是后缀(甚至是中间的某处)?
log=file.log
if grep ERRORS "$log" ; then echo BIG FAILURE ; fi
应该与任何外壳一起工作。
(感谢三人有用的评论)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.