2014-04-06 20 views
-1

我需要编写一个shell脚本,对于命令行中的每个文件,它将输出比从键盘读取的数字k更长的字数,并且他的输出必须按字数排序。我不知道如果我到目前为止已经写的,因为我得到这些错误解决了这个问题,我不知道如何解决这些问题:多个错误unix shell

./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 [email protected]; 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 
+0

提示:使用'$(whatever)'而不是反引号。这将使它更清楚。另外,什么是'>/dev $'? –

+1

另一方面 - 'bash'脚本(脚本带'#!/ bin/bash' shebang)不应该使用'.sh'扩展名。这意味着人们可以使用'sh foo.sh'运行脚本,它只保证POSIX sh行为而不保证bash扩展。最好不要使用文件扩展名,并让shebang('#!'行)完成繁重的工作。另见https://www.talisman.org/~erlkonig/documents/commandname-extensions-considered-harmful –

+0

我不同意Charles的建议;我使用'.sh'来表示一个shell脚本 - 不管shell是什么。但是我将shell脚本'编译'(复制)为不带后缀的可执行文件,所以版本控制系统存储'script.sh',但我的'bin'目录中有'script'。 –

回答

2

像错误消息告诉你,你是错过了配对为`分隔符。此外,您试图嵌套反引号,但做得不正确。

更详细,

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

(严格来说,错误信息应及时到标准错误; echo "error" >&2此外,它是很好的形式,包括错误消息$0; echo "$0: error" >&2,这样就可以从嵌套脚本告诉哪一个是有问题。)

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

(为什么你需要的值复制到n?)

 for file in [email protected]; do 

(这应该正确使用"[email protected]"为了使文件名用空格等才能正常工作。)

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

您在这里混合语法。一般语法是if command; then action; fi。一个常用命令是[,在这种情况下,其参数列表必须以结束]结束,但在这里,if似乎应该简单地检查grep的退出代码。另外,/dev$看起来像是一个错误的转录。假设这应该是/dev/null,最好简单地使用grep -q

此外,这是你有一个反向启动一个命令序列,但没有关闭backtick结束它。

因为“无法打开”是一个错误信息,它不会在标准输出中。将stderr复制到stdout,或单独处理。一种选择是反转逻辑,以便丢失的文件和没有找到的字符串转化为失败。

所以,

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

还要注意"$file"多么需要用双引号,再利用含有通配符的字符的文件名,空格等正确应对

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

这是嵌套应该会发生,但是你的语法不正确。 echo `echo foo`echo `echo bar`评估为echo fooecho bar,并且嵌套评估将是echo `echo foo\`echo \`echo bar` - 或者更易于读取且便携地使用echo $(echo foo$(echo)echo bar),其中嵌套明显并且明确。但无论如何,你的expr是完全多余的;只需直接插入值$n(或$k!)。所以;

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

其余的如果脚本看起来正确。

   echo $file": "$var 
      fi 
     done | sort -n 
    ;; 
esac 
+0

谢谢!这非常有帮助! – user1458477