저는 Bash에서 자동 숙제 채점기를 작성하고 있습니다. 그레이더는 프로그램을 컴파일하고 실행합니다. 프로그램이 컴파일 또는 실행에 실패하는 경우(예: 분할 오류로 인해) 등급은 5와 같이 고정된 작은 숫자여야 합니다. 그렇지 않으면 레벨은 프로그램 출력의 마지막 라인입니다.
마지막 행을 얻으려면 다음을 수행할 수 있습니다.
grade=$( ./a.out | tail -1 )
그러나 이는 a.out을 실행할 수 없는 경우(예: 찾을 수 없는 경우)에도 항상 종료 코드 0을 제공하므로 프로그램이 존재할 수 없는지 알 수 없습니다.
또 다른 옵션은 임시 파일을 사용하는 것입니다.
./a.out > temp
if [ $? -ne 0 ]
then
grade=0
else
grade=$( tail -1 temp )
fi
그러나 동시에 동일한 작업을 수행하는 여러 프로세스가 있는 경우 문제가 발생할 수 있습니다. 하나의 프로세스를 사용하더라도 마지막 줄만 필요할 때 모든 출력을 하나의 파일에 보관하는 것은 낭비입니다(출력이 상당히 클 수 있음).
임시 파일을 사용하지 않고 해결 방법이 있나요?
답변1
grade=$( { ./a.out 2>/dev/null || echo 0; } | tail -n 1 )
프로그램이 0이 아닌 종료 상태로 종료되거나 전혀 실행에 실패하면 실행을 시도한 ./a.out
다음 출력에 한 줄을 추가합니다. 잡혀서 에 배치 0
됩니다 .0
tail -n 1
$grade
올바르게 실행 되고 ./a.out
0 종료 상태로 종료되면 echo
트리거되지 않습니다.
/dev/null
실행 관련 진단 메시지를 보려면 표준 오류 리디렉션을 제거하세요 ./a.out
.
종료 코드를 얻으려면 0
로 변경하세요 . "$?"
숫자와 오류를 구별하려면 NaN
일부 오류 문자열을 사용해야 할 수도 있습니다.
답변2
귀하의 질문은 "임시 파일을 사용하지 않고 출력의 마지막 줄을 얻고 비정상적인 종료를 감지하고 싶습니다"로 요약됩니다. 이 경우, set -o pipefail
그 사람은 당신의 친구입니다.
다음은 인수를 실행하고 정상적으로 종료할 때 출력의 마지막 줄을 기록하는 간단한 스크립트입니다.
#!/bin/bash
[[ -x $1 ]] || {
echo >&2 "Usage ${0##*/} <PROGRAM> [ARG1] ..."
exit 1
}
set -o pipefail
program=$1
shift;
x=$($program "$@" | tail -1)
if [[ $? -eq 0 ]]; then
echo "Pass: $x"
else
echo "Fail: $?"
fi
등급 문제는 여러분에게 맡기겠습니다.