printf
1回の呼び出しで2つの別々の列に印刷したい2つの配列があります。次のように:
printf "%-${padding}s→ %s\n" "${lnFrom[@]}" "${lnTo[@]}"
出力:
dotfiles/git/gitconfig → dotfiles/hyper/hyper.css
dotfiles/hyper/hyper.js → dotfiles/nvim/nvimrc
dotfiles/nvim/warm_nature.vim → dotfiles/zsh/zshrc
~/.gitconfig → ~/.hyper.css
~/.hyper.js → ~/.nvimrc
~/.vim/colors/warm_nature.vim → ~/.zshrc
最初の3行は配列を表し、lnFrom
最後の3行はlnTo
その列になければなりません。
(padding
printfステートメントは、配列内で最も長い文字列の長さを含む変数にすぎませんlnFrom
。)
単一のprintf呼び出しを維持しながらこの問題を解決する方法についてのアイデアはありますか? (ループを導入せず)
答え1
型指定子が各配列の要素数と一致しません。配列拡張が発生すると、複数の単語が生成され、各単語には%s
一致する指定子が必要です。したがって、printf
最初の配列のすべての要素で埋め、次に2番目の配列のすべての要素で埋めます。
結合された2つの配列で印刷される要素の正確な数がわからない場合、静的書式指定子文字列をハードコードできません。 1つのアプローチは、両方の配列が展開されたときに生成される要素の総数を追跡して、フォーマット指定子配列を動的に生成することです。
count=$(( ${#lnFrom[@]} + ${#lnTo[@]} ))
これで配列を作成します。
format_specifiers=( "%-${padding}s" )
for ((i=1; i<=count-1; i++)); do
[ "$i" -eq "${#lnFrom[@]}" ] && { format_specifiers+=( " %s" ); continue; }
format_specifiers+=( "→ %s" )
done
次に、要素を次のように印刷します。
printf "${format_specifiers[*]}" "${lnFrom[@]}" "${lnTo[@]}"
上記の内容をテストした場合、->
最初の配列が終わる部分と次の配列が始まる部分の間に追加の項目が含まれることがあります。これは、型指定子配列を作成するときに配列の開始/終了位置を決定しなかったためです。
あなたはこれを行うことができます
for ((i=1; i<=count-1; i++)); do
[ "$i" -eq "${#lnFrom[@]}" ] && { format_specifiers+=( " %s" ); continue; };
format_specifiers+=( "→ %s" )
done