سؤال

I need to write a shell script that for each file from the command line will output the number of words that are longer than a number k read from keyboard and he output must be ordered by the number of words. I don't know if what I've written so far solves the problem because I get these errors and I don't know how to fix them:

./b.sh: command substitution: line 19: unexpected EOF while looking for matching `''
./b.sh: command substitution: line 20: syntax error: unexpected end of file
./b.sh: command substitution: line 19: unexpected EOF while looking for matching `''
./b.sh: command substitution: line 20: syntax error: unexpected end of file
./b.sh: line 19: 5: command not found

#!/bin/bash
case $# in
    0)
        echo "The script cannot be executed due to missing arguments!"
        exit 1
    ;;
    *)
        read -p "Enter the length: " k
        n=$k
        for file in $@; do
            if [ `file $file | egrep "exec|data|empty|reloc|cannot open" > /dev$
                continue
            else
                var=`tr ' ' '\n' < $file | grep -c '^.\{`expr $n`\}$'`
                echo $file": "$var
            fi
        done | sort -n
    ;;
esac
هل كانت مفيدة؟

المحلول

Like the error message tells you, you are missing the pair for a ` delimiter. Also, you have attempted to nest backticks, but done it incorrectly.

In more detail,

#!/bin/bash
case $# in
    0)
        echo "The script cannot be executed due to missing arguments!"
        exit 1
    ;;

(Strictly, error messages should go to stderr; echo "error" >&2. Also, it is good form to include $0 in the error message; echo "$0: error" >&2 so that you can tell from nested scripts which one is having a problem.)

    *)
        read -p "Enter the length: " k
        n=$k

(Why do you need to copy the value to n?)

        for file in $@; do

(This should properly use "$@" in order for file names with spaces etc to work correctly.)

            if [ `file $file | egrep "exec|data|empty|reloc|cannot open" > /dev$
            continue

You are mixing syntax here. The general syntax is if command; then action; fi. One commonly used command is [ in which case its argument list must end with a closing ], but here, it seems that if should simply examine the exit code from grep. Also, /dev$ looks like an erroneous transcription. Assuming this was meant to be /dev/null, better simply use grep -q.

Also, this is where you have a backtick which starts a command sequence, but no closing backtick to end it.

Because "cannot open" is an error message, it wil not be in standard output. Either copy stderr to stdout, or handle separately. One option is to invert the logic, so that both a missing file and the absence of the strings you are looking for translates to failure.

So,

if ! file "$file" | grep -vEq "exec|data|empty|reloc"; then
    continue

Notice also how "$file" needs to be double quoted, again to cope correctly with file names containing wildcard characters, whitespace, etc.

            else
                var=`tr ' ' '\n' < $file | grep -c '^.\{`expr $n`\}$'`

This is where the nesting is supposed to happen, but your syntax is incorrect. echo `echo foo`echo `echo bar` evaluates to echo fooecho bar, and nested evaluation would be echo `echo foo\`echo \`echo bar` -- or more readably and portably, use echo $(echo foo$(echo )echo bar) where the nesting is obvious and unambiguous. But anyway, your expr is completely superfluous; just interpolate the value if $n (or $k!) directly. So;

var=$(tr ' ' '\n` <"$file" | grep -c "^\{$k\}")

The rest if the script looks correct.

                echo $file": "$var
            fi
        done | sort -n
    ;;
esac
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top