【问题标题】:How to format a number in bash, possibly with printf?如何在 bash 中格式化数字,可能使用 printf?
【发布时间】:2014-06-09 13:17:12
【问题描述】:

这个简单的脚本失败了:

#!/bin/bash
n=1
printf -v fn "%05d" $n
echo $fn

与

3: printf: Illegal option -v

为什么! (ubuntu 14.04)

【问题讨论】:

  • 你说得对,我在 ubuntu 上用 sh 调用了脚本。现在不知道区别了。谢谢乔!!
  • !!!我的天啊 !!!那是对的!在 Mac OS X 上,“sh”和“bash”是一回事,用sh 调用没有区别。但在 Ubuntu 上,我得到了你得到的确切行为!
  • Debian 及其衍生版本使用dash 作为它们的默认 shell。见wiki.ubuntu.com/DashAsBinSh。
  • @Flortify 甚至比这更复杂一些。在 OSX 上,sh 和 bash默认情况下是相同的。但根据您的PATH 以及您是否安装了更新版本的bash,它们可能会有所不同。对我来说,bash 是 4.3.18(1)-release,sh 是 3.2.48(1)-release。

标签: bash printf


【解决方案1】:

根据@Joe,这似乎与Whats the difference between running a shell script as ./script.sh and sh script.sh 重复。

根据@Telemachus,Debian 及其衍生版本使用 dash 作为默认 shell。请参阅http://wiki.ubuntu.com/DashAsBinSh 了解更多信息。

这是我在 Ubuntu 系统上看到的:

$ ls -lF `which sh`
lrwxrwxrwx 1 root root 4 Aug 15  2012 /bin/sh -> dash*
$ ls -lF `which bash`
-rwxr-xr-x 1 root root 959168 Mar 30  2013 /bin/bash*

这解释了为什么我无法在 Mac OS X 10.8.5 上重现该问题。我确实在 Ubuntu 上通过使用 sh 而不是 bash 调用脚本来重现它。

我将保留我的其余答案,因为它展示了您可能采取的一些步骤来解决问题。

你能检查一下你的 bash 版本吗?

$ bash --version
bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)

这还能用吗?

#!/bin/bash
n=1
printf -v fn "%05d" $n
echo $fn

检查名称printf的类型?

$ type printf
printf is a shell builtin
$ function printf { echo "giggle" ; }
giggle
$ type printf
printf is a function
printf () 
{ 
    echo "giggle"
}
giggle
$ 

查看 printf 内置的内置帮助?

$ help printf
help printf

printf: printf [-v var] format [arguments]
    printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT
    is a character string which contains three types of objects: plain
    characters, which are simply copied to standard output, character escape
    sequences which are converted and copied to the standard output, and
    format specifications, each of which causes printing of the next successive
    argument.  In addition to the standard printf(1) formats, %b means to
    expand backslash escape sequences in the corresponding argument, and %q
    means to quote the argument in a way that can be reused as shell input.
    If the -v option is supplied, the output is placed into the value of the
    shell variable VAR rather than being sent to the standard output.

内置的printf 是否被其他地方的定义替换了?这是我用来检查 shell 中名称定义的函数:

list () 
{ 
    if [[ 0 == $# ]]; then
        Log "";
        Log "FUNCTIONS:";
        Log "----------";
        declare -F;
        Log "";
        Log "EXPORTS:";
        Log "--------";
        export -p;
        Log "";
        Log "PRINTENV:";
        Log "--------";
        printenv;
    else
        while [[ ! -z "$1" ]]; do
            local name="$1";
            shift;
            if ! alias "${name}" 2> /dev/null; then
                if ! declare -f "${name}"; then
                    if ! help "${name}" 2> /dev/null; then
                        if ! which "${name}"; then
                            Log "Not found: '${name}'";
                        fi;
                    fi;
                fi;
            fi;
        done;
    fi
}

这是我在新的 shell 中运行时的输出:

$ list printf
printf: printf [-v var] format [arguments]
    printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT
    [… snip …]

但如果我重新定义printf,它将显示定义:

$ function printf { echo "kibble" ; }
kibble
$ printf
kibble
kibble
$ list printf
printf () 
{ 
    echo "kibble"
}
kibble
$ 

我很想知道这里到底发生了什么!!!

我喜欢其他答案的建议,即尝试使用 bash 显式调用脚本:

$ bash myscript.sh

这是我在 Ubuntu 服务器上看到的:

$ uname -a
Linux rack 3.11.0-17-generic #31-Ubuntu SMP Mon Feb 3 21:52:43 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ cat > dme.sh
#!/bin/bash
n=1
printf -v fn "%05d" $n
echo $fn
$ chmod +x ./dme.sh
$ ./dme.sh
00001
$ bash dme.sh
00001
$ sh dme.sh
dme.sh: 3: printf: Illegal option -v

【讨论】:

  • 请注意,您可以通过type 找到有关printf 和其他功能的信息。 type printf 产生(通常)printf is a shell builtin。
  • @konsolebox 我已经编辑了答案,把最简单的答案放在第一位。我保留了其余的答案,以展示如何解决类似问题。我认为这是有价值的。 “授人以鱼,养人一日;授人以渔,养人一生。”
  • 很抱歉,即使您回答的第一部分也不够简单。实际上,我会把乔的答案作为一个简单答案的候选人,尽管这是我在 JulienFr 回复我之后发布的一个明显的衍生答案。我实际上发现它没有必要,因为我的观点已经很明显了。没有必要给出切线。
【解决方案2】:

您可能正在使用尚不支持-v 选项的 Bash 版本。尝试运行bash --version。它应该是 3.1 或更高版本。

另外,请确保您确实使用 bash 运行脚本。尝试显式调用bash script.sh。

【讨论】:

  • bash --version 提供 GNU bash,版本 4.3.11(1)-release (x86_64-pc-linux-gnu)
【解决方案3】:

您将脚本作为/bin/sh 的参数运行,如下所示:

$ sh script.sh 
script.sh: 3: printf: Illegal option -v

忽略#! 行。运行它:

$ ./script.sh
00001

改为。

【讨论】:

  • 也许在 Debian 及其衍生产品和此链接上添加 dash 为 /bin/sh? wiki.ubuntu.com/DashAsBinSh(我将在下面删除我的答案。)
【解决方案4】:

正如其他答案告诉您的那样,旧 BASH 版本不支持 printf -v,但您可以在旧 BASH 中设置fn:

#!/bin/bash
n=1
fn=$(printf "%05d" "$n")
echo "$fn"

【讨论】:

    猜你喜欢
    • 2020-01-03
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-19
    • 2021-03-23
    相关资源
    最近更新 更多