Код ниже дублируется дважды в полном скрипте, как этого избежать?
if jurge_expr ; then
(( retry_cnt += 1 ))
echo $CS2
echo "reading CS2 checking failed. retry, retry_cnt=$retry_cnt"
if [[ $retry_cnt -gt $max_retry_cnt ]]; then
echo "$RED retry too many times, failed to write 0xe2 $bytes 2 $filename $RESET"
break;
fi
sleep 0.5
continue;
fi
Вот полный сценарий:
# Loop through each filename in sorted_files and print it
set -- $sorted_files
for filename; do
addr=$(echo "$filename" | cut -d_ -f1)
bytes=$(echo "$filename" | cut -d_ -f2 | sed -e 's/B.dat//' -e 's/KB.dat//')
retry_cnt=0;
while true;
do
echo "bulk writing 0xe2 $bytes 2 $filename"
ccidbgr /dev/cci2 0x6d bulkWrite 0xe2 $bytes 2 $filename
sleep 0.5
echo "reading CS2"
CS2=$(ccidbgr /dev/cci2 0x6d read 0xF2 2>&1)
if [[ $? -ne 0 ]]; then
(( retry_cnt += 1 ))
echo $CS2
echo "reading CS2 checking failed. retry, retry_cnt=$retry_cnt"
if [[ $retry_cnt -gt $max_retry_cnt ]]; then
echo "$RED retry too many times, failed to write 0xe2 $bytes 2 $filename $RESET"
break;
fi
sleep 0.5
continue;
fi
echo $CS2
CS2=$(echo $CS2 | cut -dx -f3)
if [[ $CS2 -eq 0 ]]; then
(( retry_cnt += 1 ))
echo "read CS2 is zero. retry, retry_cnt=$retry_cnt"
if [[ $retry_cnt -gt $max_retry_cnt ]]; then
echo "$RED retry too many times, failed to write 0xe2 $bytes 2 $filename $RESET"
break;
fi
sleep 0.5
continue;
fi
done
done
@ user1934428 В ответе @Ivan упоминается function, но я не уверен, что break в function может остановить внешний цикл. Подробности смотрите в моем комментарии к указанному ответу.
С точки зрения проектирования функция никогда не должна сама решать, что цикл, вызывающий функцию, должен быть завершен. В программировании мы либо возвращаем код вызывающей стороне и позволяем вызывающей стороне решить, что делать в этом случае, либо, возможно, вызываем исключение (или, в некоторых языках, используем продолжение). В ksh код может быть возвращен как код выхода (с использованием оператора return), а исключение может быть смоделировано с помощью kill (что тогда необходимо вызывающему абоненту trap). Продолжения в кш нет. Я почти уверен, что вариант с кодом возврата доставит вам меньше головной боли.
Кстати, не используйте ключевое слово function — это отход от синтаксиса ksh 1980-х годов, который bash поддерживает только для обратной совместимости. Без него функция — это просто функция, а не function. :)





Функция? Учти это:
...
fun(){
(( retry_cnt += 1 ))
echo $CS2
echo "reading CS2 checking failed. retry, retry_cnt=$retry_cnt"
if [[ $retry_cnt -gt $max_retry_cnt ]]; then
echo "$RED retry too many times, failed to write 0xe2 $bytes 2 $filename $RESET"
return 1
fi
sleep 0.5
return 2
}
...
[[ $? -ne 0 ]] && { fun; case $? in 1) break;; 2) continue;; esac;}
...
[[ $CS2 -eq 0 ]] && { fun; case $? in 1) break;; 2) continue;; esac;}
...
Или вот так:
...
fun(){
(( retry_cnt += 1 ))
echo $CS2
echo "reading CS2 checking failed. retry, retry_cnt=$retry_cnt"
if [[ $retry_cnt -gt $max_retry_cnt ]]; then
echo "$RED retry too many times, failed to write 0xe2 $bytes 2 $filename $RESET"
return 0
fi
sleep 0.5
return 1
}
...
[[ $? -ne 0 ]] && { fun && break || continue ;}
...
[[ $CS2 -eq 0 ]] && { fun && break || continue ;}
...
Этот выглядит лучше.
В моем фрагменте кода break используется для остановки цикла while. Если break инкапсулирован в func(), внешний цикл while все равно можно остановить?
@Джон, да, ты прав, в этом случае нужно использовать return, а еще есть continue... Совсем не весело)
Обновил return, но выглядит некрасиво)
В этом конкретном случае я бы, вероятно, объединил два (почти) повторяющихся блока кода в один блок, используя несколько новых переменных, чтобы облегчить логический поток.
Одна идея:
set -- $sorted_files
for filename; do
addr=$(echo "$filename" | cut -d_ -f1)
bytes=$(echo "$filename" | cut -d_ -f2 | sed -e 's/B.dat//' -e 's/KB.dat//')
retry_cnt=0;
while true;
do
echo "bulk writing 0xe2 $bytes 2 $filename"
ccidbgr /dev/cci2 0x6d bulkWrite 0xe2 $bytes 2 $filename
sleep 0.5
echo "reading CS2"
CS2=$(ccidbgr /dev/cci2 0x6d read 0xF2 2>&1)
###################################### new/replacement code (start)
rc=$? # save return code
IFS='x' read -ra cval <<< "$CS2" # split CS2 on delimiter "x" into array cval[]
msg = "" # clear msg
# test two new vars (rc, cval[2])
[[ "$rc" -ne 0 ]] && { echo "$CS2"; msg = "reading CS2 checking failed. retry, retry_cnt=$retry_cnt"; }
[[ "${cval[2]}" -eq 0 ]] && { msg = "read CS2 is zero. retry, retry_cnt=$retry_cnt" ; }
if [[ -n "$msg" ]] # if msg is not empty then one of the 2 tests was 'true' so ...
then
(( retry_cnt++ ))
echo "$msg"
if [[ $retry_cnt -gt $max_retry_cnt ]]; then
echo "$RED retry too many times, failed to write 0xe2 $bytes 2 $filename $RESET"
break;
fi
sleep 0.5
continue;
fi
###################################### new/replacement code (end)
done
done
ПРИМЕЧАНИЯ: у меня нет среды для тестового запуска этого кода, но shellcheck.net не сообщает ни о каких синтаксических ошибках.
Что говорит против помещения его в функцию?