printf 输出行,而不是列

printf 输出行,而不是列

我有两个数组,我想通过一次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,它们应该位于各自的列上。

paddingprintf 语句中只是一个包含数组中最长字符串长度的变量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

相关内容