简体   繁体   中英

How to format a number in bash, possibly with printf?

This so simple script is failing :

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

with

3: printf: Illegal option -v

WHY !!! (ubuntu 14.04)

You're probably using a version of Bash not supporting -v option yet. Try running bash --version . It should be 3.1 or newer.

Also, make sure you do run your script with bash. Try explicitly calling bash script.sh .

Per @Joe, this appears to be a duplicate of Whats the difference between running a shell script as ./script.sh and sh script.sh .

Per @Telemachus, Debian and its derivatives use dash as their default shell. See http://wiki.ubuntu.com/DashAsBinSh for more information.

Here's what I see on an Ubuntu system:

$ 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*

That explains why I was not able to reproduce the issue on Mac OS X 10.8.5. I did reproduce it on Ubuntu by invoking the script with sh instead of bash .

I'm leaving the rest of my answer in place since it demonstrates some steps you might take to troubleshoot the problem.

Can you check your version of bash?

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

Does this even work?

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

Check the type of the name printf ?

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

Check the builtin help for the printf builtin?

$ 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.

Has the builtin printf been replaced by a definition from somewhere else? Here's a function I use for checking the definition of names in the 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
}

Here's the output when I run this in a fresh shell:

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

But if I redefine printf , it will show the definition:

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

I am curious to hear what's really going on here!!!

I like the other answer's suggestion to try invoking the script explicitly w/ bash:

$ bash myscript.sh

Here's what I see on an Ubuntu server:

$ 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

You're running the script as an argument to /bin/sh , like this:

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

which ignores the #! line. Run it as:

$ ./script.sh
00001

instead.

As other answers tell you that older BASH version versions don't support printf -v but here is what you can do that in older BASH to set fn :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM