오류 메시지의 접두사 및 리디렉션을 위한 printf와 같은 작업을 위한 래퍼

오류 메시지의 접두사 및 리디렉션을 위한 printf와 같은 작업을 위한 래퍼

내 POSIX 쉘 코드 error에 함수가 있습니다 . sh본질적으로 다음과 같습니다

error () {
    printf 'utility: ERROR: ' >&2
    printf "$@" >&2
}

두 번째는 printf예를 들어 함수를 호출할 수 있게 해줍니다.

error 'Something relating to "%s" went wrong!\n' "$thing"
exit 1

이 함수는 메시지 앞에 문자열을 추가 utility: ERROR:하고 모든 항목이 표준 오류로 전송되도록 준비합니다. 하지만 여전히 printf.

확실히,주택 검사두 번째 사람에게 불평 printf하세요.

SC2059: printf 형식 문자열에 변수를 사용하지 마세요. printf "..%s.." "$foo"를 사용하세요.

내가 한 일을 하고 이 경고를 무시하는 것이 "안전"합니까?장애를 입히다# shellcheck disable=SC2059코드에 주석이 달려 있나요 ?) 나는 항상 내 error기능을 사용합니다.정확히그렇지 않으면 을 사용합니다 printf. 즉, 첫 번째 매개변수에 정적 작은따옴표를 사용합니다.

"안전합니까?" 여기서 의미하는 것은 "내 기능이 printf(리디렉션 외에) 유사한 작업에 대한 래퍼로서 적절한 방식으로 작동합니까?" 입니다.

답변1

여기서 형식을 매개변수로 전달하려고 하므로 이는 안전합니다. 하지만 함수를 사용할 때에는 형식이라는 점을 기억해야 합니다. 따라서 함수 이름을 errorf미리 알림으로 지정해야 할 수도 있습니다.

다음과 같이 사용하는 경우:

error "invalid arg: $arg"

$arg다음과 같은 문제를 일으키게 됩니다.%99999999s

이상적으로는 shellcheck에 무시하라고 지시하고 싶습니다.printf 그리고printf첫 번째 매개변수에 포함된 변수의 사용법을 표시할 수 있습니다 .

몇 가지 참고사항:

  • 두 번 호출했으므로 printf최소 2번의 write()시스템 호출이 있습니다. 아무런 차이가 없을 것 같습니다. printfs와 같은 일부 구현은 경우에 따라 여러 시스템 호출을 수행하기도 합니다. bash그런 종류질문내가 염두에 둔 것은 오류 메시지의 두 부분이 병렬로 실행되는 다른 명령의 출력과 얽혀 있다는 것입니다.
  • 접두사의 error "%s\n" error1 error2첫 번째 오류만 인쇄됩니다. 그렇게 하고 싶다면 괜찮습니다. 다음과 같이 할 수도 있습니다.

    errorf() { printf "utility: ERROR: $@" >&2; }
    

    형식을 재사용할 때마다 출력되도록 형식에 접두사를 추가합니다. (이렇게 하면 여러 문제도 해결됩니다.)write() 질문).

    utility그러나 변수가 되고 싶다면 작동하지 않습니다.

    PROG_NAME=${0##*/}
    errorf() { printf >&2 "$PROG_NAME: 오류: $@" }
    
    아니요. 또는 을 $0포함 하면 %실패하기 때문입니다 \.

    그리고

    PROG_NAME=${0##*/}
    실수(){
    형식=$1;전송
    printf >&2 "%s: 오류: $format" "$PROG_NAME" "$@"
    }
    재사용된 형식의 경우에는 작동하지 않습니다(그리고 사용자가 지침을 하나씩 오프셋해야 함을 의미합니다 %<n>$d(이 지침은 이식성이 없기 때문에 사용하는 것이 좋습니다).)

    \and 를 수동으로 이스케이프 처리하는%$PROG_NAMEprintf0x5c\

관련 정보