如何使用带条件参数的 printf

How to use printf with conditional arguments

如果 $files 为 0 或 1,我尝试打印 file,如果大于 1,则打印 files。在 [=23= 中执行此操作的简洁方法是什么]?

我尝试使用 'printf' 如下,

files=13;
printf 'There are %s file%s' $files $(($files > 1 ? 's' : ''))

正如预期的那样,这是行不通的。

有人能告诉我如何实现吗?

创建这样的条件:

printf 'There are %s file%s\n' $files $( [ $files -gt 1 ] && echo "s")

使用 $( [ $files -gt 1 ] && echo "s" || echo "") 我们将打开一个 shell,在其中检查值。如果条件匹配,则打印 s

要同时处理 is/are,您可以添加另一个条件:

printf 'There %s %s file%s\n' $( [ $files -eq 1 ] && echo "is" || echo "are" ) $files $( [ $files -gt 1 ] && echo "s")

测试

$ files=0
$ printf 'There are %s file%s\n' $files $( [ $files -gt 1 ] && echo "s")
There are 0 file
$ files=1
$ printf 'There are %s file%s\n' $files $( [ $files -gt 1 ] && echo "s")
There are 1 file
$ files=15
$ printf 'There are %s file%s\n' $files $( [ $files -gt 1 ] && echo "s")
There are 15 files

好吧,实际上,如果你想在语法上 正确 输出("are" 与 "is"),你也可以写出来而不是试图用一条线凑合...

if [[ $files -eq 1 ]]
then
    echo "There is 1 file."
else
    echo "There are $files files."
fi

更好读,出错的可能性更小,而且可能更快,因为它只进行一次测试,并且不启动子 shell。

如果它只是在 filefiles 之间进行选择,您可以这样做,尽管它并不像人们希望的那样简洁:

printf "The search found %d file%.*s.\n" $files $((files != 1)) "s"

但在 OP 的声明中,您还需要将 are 更改为 is 以保持 verb/object 协议。在这种情况下,使用条件语句几乎肯定更容易且更具可读性,但您可以使用数组:

formats=("is %d file" "are %d files")
printf "There ${formats[files!=1]}.\n" $files

因为 %b 格式说明符解释反斜杠转义,您仍然可以使用 ? 运算符替换单个字符。

$ files=1
$ printf 'Removed %s file%b\n' $files \$(($files > 1 ? 163 : 0))
Removed 1 file

$ files=15
$ printf 'Removed %s file%b\n' $files \$(($files > 1 ? 163 : 0))
Removed 15 files