/usr/bin/printf または Bash printf で指定された順序でパラメータを処理します。

/usr/bin/printf または Bash printf で指定された順序でパラメータを処理します。

はじめに。私はこの言語でCこのprintf関数が次のことを行うことができることを知っています:

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

GNUawkまたはGNUperlもこれをサポートしているため、どちらかがインストールされている場合は、次の関数で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が番号付き変換指定子と番号なし変換指定子の混合を定義されていないと説明していることを考慮すると、これは合理的だと思います。

関連情報