/usr/bin/printf 또는 Bash printf에서 지정된 순서로 매개변수를 처리합니다.

/usr/bin/printf 또는 Bash printf에서 지정된 순서로 매개변수를 처리합니다.

머리말. 나는 이 언어에서 Cprintf함수가 다음을 수행할 수 있다는 것을 알고 있습니다:

printf('%2$s %2$s %1$s %1$s', 'World', 'Hello');

산출:Hello Hello World World

하지만 이 기능은 GNU Bash에서는 지원되지 않는 것 같습니다.

printf '%2$s %2$s %1$s %1$s' 'World' 'Hello'

산출:bash: printf: $': invalid format character

나는 또한 local을 사용해 보았습니다 /usr/bin/printf.

/usr/bin/printf '%2$s %2$s %1$s %1$s' 'World' 'Hello'

산출:/usr/bin/printf: %2$: invalid conversion specification

CBash에서 동작을 얻는 방법은 무엇입니까 ? 감사해요.

편집하다:

이 동작이 궁금하며 매개변수 순서를 변경하는 해결 방법을 받아들일 수 없습니다. 형식 문자열만 사용해도 작동합니다.

편집하다:

예를 들어 GNU Bash 소스 코드 국제화를 고려해보세요. 이 기능이 없으면 매우 불가능합니다.

답변1

bash넌 이것 과 경쟁할 수 없어printf유틸리티에 대한 POSIX 사양지원되지도 않습니다. 매개변수를 수동으로 다시 정렬해야 합니다.

printf및 (또는 print -f) 내장 함수가 ksh93이를 지원합니다 zsh:

$ printf '%2$s%1$s\n' a b
ba

GNU awk또는 GNU perl도 이를 지원하므로 둘 중 하나가 설치되어 있으면 다음과 같은 함수로 bash재정의할 수 있습니다 .printf

printf() { zsh -c '"$0" "$@"' printf "$@"; }

또는:

printf() { ksh93 -c '"$0" "$@"' printf "$@"; }

gawk사용하거나 더 많은 노력이 필요합니다. 그대로 전달할 수 없고 시퀀스를 확장하지 않으며 (큰따옴표 안에 코드로 축어적으로 전달 되지 않는 한) 지원하지 않기 perl때문 입니다( 시뮬레이션용 유틸리티 확장). V ).gawkARGVgawkperl\x%bprintfecho

답변2

printf를 함수로 재정의하면 다른 프로세스를 호출하지 않고도 bash가 이 작업을 수행할 수 있습니다.

printf() {  # add support for numbered conversion specifiers
    local -a args
    local opt=
    case $1 in
    -v) opt=-v$2; shift 2;;
    -*) opt=$1; shift;;
    esac
    local format=$1; shift
    while [[ $format =~ ((^|.*[^%])%)([0-9]+)\$(.*) ]]
    do
        args=("${!BASH_REMATCH[3]}" "${args[@]}")
        format=${BASH_REMATCH[1]}${BASH_REMATCH[4]}
    done
    let ${#args[@]} && set -- "${args[@]}"
    builtin printf $opt "$format" "$@"
}

이는 형식 문자열의 번호가 있는 변환 지정자를 번호가 없는 변환 지정자로 바꾸는 동시에 숫자를 사용하여 수정된 매개변수 목록에 대한 매개변수를 선택함으로써 수행됩니다. 숫자 변환 지정자가 없으면 printf 내장 함수는 함수의 인수를 있는 그대로 봅니다. 놀라운 동작이 거의 없는 간단한 교체여야 합니다.

bash 정규식 일치는 욕심이 많기 때문에 새 인수 목록을 작성하는 명령문의 순서는 놀랄 수 있습니다. 따라서 while 루프가 찾을 때마다 새 인수를 추가하는 대신 args[] 배열 앞으로 푸시해야 합니다. 숫자 변환 지정자는 형식 문자열에 남아 있는 마지막 지정자가 됩니다.

또한 변환 지정자를 포함하는 형식 문자열보다 더 많은 인수가 전달되면 숫자 지정자에 해당하지 않는 인수가 있을 때 printf 내장에서 일반적으로 수행되는 형식 문자열 재활용이 발생하지 않습니다. 그냥 무시하세요. POSIX가 번호가 있는 변환 지정자와 번호가 없는 변환 지정자의 혼합을 정의되지 않은 것으로 설명한다는 점을 고려하면 이것이 합리적이라고 생각합니다.

관련 정보