我有两个数组,我想通过一次printf
调用将其打印在两个单独的列中。下列:
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
前三行代表数组lnFrom
,最后三行lnTo
,它们应该位于各自的列上。
(padding
printf 语句中只是一个包含数组中最长字符串长度的变量lnFrom
)
关于如何在保持单个 printf 调用的同时解决这个问题的想法? (不引入任何循环)
答案1
您的格式说明符与每个数组中存在的元素数量不匹配。一旦发生数组扩展,就会生成多个单词,每个单词都需要一个%s
说明符来匹配。因此,printf
只需用第一个数组的所有元素填充它们,然后用第二个数组的所有元素填充它们。
除非您知道从组合的两个数组中打印的元素的确切数量,否则无法对静态格式说明符字符串进行硬编码。一种方法是动态生成格式说明符数组,方法是跟踪两个数组都扩展时将生成的元素总数
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