for
loop 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
}
Обратите внимание на добавление grep
после make
.&&
говорит "и", а !
инвертирует код выхода из grep
(так что это верно, если grep
не может найти совпадения).-q
подавляет вывод совпадений на grep
и приводит к тому, что поиск прекращается, как только он находит первое совпадение.
Более тангенциально, я бы считал pushd
и popd
предназначенными дляинтерактивное использование.Сценарии оболочки, как правило, просто cd
в подоболочке, а затем, когда она завершается, вы возвращаетесь в каталог, в котором вы начали.Но здесь может потребоваться более фундаментальный рефакторинг.
Для более сложного, но, надеюсь, надежного рефакторинга, возможно, сделайте
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
фактическим именем файла теста или просто суффиксом (или даже где-то посередине)?