简体   繁体   中英

Bash Script to function as wc command

I am trying to create a script using getopts that would work as wc . the problem is that I get stuck when I use two switches together. The script:

while getopts l:w:c: choice
do
         case $choice in
               l) wc -l $OPTARG;;
               w) wc -w $OPTARG;;
               c) wc -c $OPTARG;;
               ?) echo wrong option.
         esac
done

When I run this script with ./script.sh -l file it works, but when I use ./script -wl file it just goes into an infinite loop. Can anyone please explain what's going on and how to fix it?

You're using it incorrectly. As per the getopts manual :

If a letter is followed by a colon , the option is expected to have an argument.

And in your example you're not passing argument for -w and -l options;

Correct usage is:

./script -w file1 -l file2

Which will process both options correctly.

Otherwise to support an option without argument just use it without colon like this:

while getopts "hl:w:c:" choice

Here option h will not need an argument but l, w, c will support one.

You need to build the options in the case statement and then execute wc :

# Set WC_OPTS to empty string
WC_OPTS=();
while getopts lwc choice
do
     case $choice in
            l) WC_OPTS+='-l';;
            w) WC_OPTS+='-w';;
            c) WC_OPTS+='-c';;
            ?) echo wrong option.
     esac
done
# Call wc with the options
shift $((OPTIND-1))
wc "${WC_OPTS[@]}" "$@"

To add to the other comments . . . the version of wc that I have handy seems to handle its options like this:

#!/bin/bash

options=()
files=()

while (( $# > 0 )) ; do
    if [[ "$1" = --help || "$1" = --version ]] ; then
        wc "$1"   # print help-message or version-message
        exit
    elif [[ "${1:0:1}" = - ]] ; then
        while getopts cmlLw opt ; do
            if [[ "$opt" = '?' ]] ; then
                wc "$1"   # print error-message
                exit
            fi
            options+="$opt"
        done
        shift $((OPTIND-1))
        OPTIND=1
    else
        files+="$1"
        shift
    fi
done

wc "${options[@]}" "${files[@]}"

(The above could be refined further, by using a separate variable for each of the five possible options, to highlight the fact that wc doesn't care about the order its options appear in, and doesn't care if a given option appears multiple times.)

Got a workaround.

#!/bin/bash

if [ $# -lt 2 ]
then

    echo not a proper usage
    exit

fi

file=$2

while getopts wlc choice

do

    case $choice in 

        l) wc -l $file
            ;;
        w) wc -w $file
            ;;
        c) wc -c $file
            ;;
        ?) echo thats not a correct choice

    esac
done

I think I got obsessed with OPTARG, thanks everyone for your kind help 

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