【问题标题】:Why does the Bourne shell printf iterate over a %s argument?为什么 Bourne shell printf 会遍历 %s 参数?
【发布时间】:2010-09-07 17:02:45
【问题描述】:

这是怎么回事?

printf.sh:

#! /bin/sh
NAME="George W. Bush"
printf "Hello, %s\n" $NAME

命令行会话:

$ ./printf.sh
Hello, George
Hello, W.
Hello, Bush

更新:printf "Hello, %s\n" "$NAME" 有效。为什么我不使用echo,请考虑

echo.sh:

#! /bin/sh
FILE="C:\tmp"
echo "Filename: $FILE"

命令行:

$ ./echo.sh
Filename: C:    mp

POSIX spec for echo 表示,“鼓励新应用程序使用 printf 而不是 echo”(出于此原因和其他原因)。

【问题讨论】:

  • bash 内置回声默认情况下不会执行 \ 替换,但 POSIX shell(例如破折号)回声会执行,正如您指向规范的链接所示。由于您无论如何都在使用外壳,因此您可以 printf "Hello, $NAME\n"
  • 实际上,出于安全性和正确性的原因,使用 %s 可能是一个好习惯。 printf 将对格式字符串进行 \ 替换和其他操作,因此请尽可能避免使用变量。

标签: unix shell


【解决方案1】:

您的 NAME 变量被这样替换:

printf "Hello, %s\n" George W. Bush

使用这个:

#! /bin/sh
NAME="George W. Bush"
printf "Hello, %s\n" "$NAME"

【讨论】:

    【解决方案2】:

    您使用 printf 是否有特定原因,或者 echo 也适合您?

    NAME="George W. Bush"
    echo "Hello, "$NAME
    

    结果

    Hello, George W. Bush
    

    编辑: 它迭代“George W. Bush”的原因是因为 bourne shell 是用空格分隔的。要继续使用 printf,您必须将 $NAME 放在双引号中

    printf "Hello, %s\n" "$NAME"
    

    【讨论】:

      【解决方案3】:

      我解释man page 的方式是将您传递给它的字符串视为参数;如果您的字符串有空格,它认为您正在传递多个参数。我相信 ColinYounger 用引号将变量括起来是正确的,这会强制 shell 将字符串解释为单个参数。

      另一种方法可能是让 printf 扩展变量:

      printf "Hello, $NAME."
      

      这些链接适用于 bash,但我很确定 sh 也是如此。

      【讨论】:

      • 不,没有“它认为”。他确实传递了多个参数,因为他没有在 printf 命令中引用 $NAME 的扩展。 shell 扩展它,然后对其进行字拆分,然后将 3 个参数传递给 printf。但正如你所说,ColinYounger 是对的。
      【解决方案4】:

      如果您想单独打印所有这些单词,请使用 print 而不是 printf

      printf 采用格式规范并将其应用于您传入的每个参数。由于您有三个参数 {George, W., Bush},它使用不同的参数输出字符串三次.

      【讨论】:

      • print(1) 用于在检查文件的 mime 类型后将文件打印到打印机。它不是 bash 中内置的 shell。
      猜你喜欢
      • 2014-04-12
      • 2011-06-12
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 2015-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多