我该如何改进这个脚本?

时间:2012-04-08 23:26:29

标签: bash shell

我正在学习shell脚本,并且很难找到一种好的学习方法。我在下面创建了一个脚本,允许用户通过选项搜索各种不同的Internet引擎。如果有人能够仔细研究并指出我做错了什么,如何改进它等等,我将非常感激。

#!/bin/bash

## Get user search-engine option
while getopts aegwy: OPTIONS ; do
  case "$OPTIONS" in 
    a) ENGINE="http://www.amazon.com/s/ref=nb_sb_noss/?field-keywords";;
    e) ENGINE="http://www.ebay.com/sch/i.html?_nkw";;
    g) ENGINE="http://www.google.com/search?q";;
    w) ENGINE="http://en.wikipedia.org/wiki/?search";;
    y) ENGINE="http://www.youtube.com/results?search_query";;
    ?) ERRORS=true;;
  esac
done &>/dev/null

## Ensure correct command usage
[ $# -ne 2 ] || [ $ERRORS ] && printf "USAGE: $(basename $0) [-a Amazon] [-e eBay] [-g Google] [-w Wikipedia] [-y YouTube] \"search query\"\n" && exit 1

## Ensure user is connected to the Internet
ping -c 1 209.85.147.103 &>/dev/null ; [ $? -eq 2 ] && printf "You are not connected to the Internet!\n" && exit 1

## Reformat the search query
QUERY=`printf "$2" | sed 's/ /+/g'`

## Execute the search and exit program
which open &>/dev/null ; [ $? -eq 0 ] && open "$ENGINE"="$QUERY" &>/dev/null && exit 0 || xdg-open "$ENGINE"="$QUERY" &>/dev/null && exit 0 || printf "Command failed!\n" && exit 1

先谢谢大家,意味着很多!

2 个答案:

答案 0 :(得分:2)

最好发布在codereviews中,如上所示,但这里有一些主要是风格的评论。我应该强调脚本是非常好的原样;这些只是一些小改进,我认为这将有助于使代码更易于阅读/维护,在几种情况下更加强大等等。

您不需要为变量名使用全大写,因为环境变量是全大写的; shell变量和环境变量不是一回事。

由于您的$OPTIONS变量一次只能包含一个选项,因此单数名称会更好(例如$option)。或者你可以选择$opt,这在某种程度上是传统的。

你的getopts字符串中的:aegwy:)表示-y选项需要参数,如-y 某事而不是只是-y本身。由于你没有对$OPTARG做任何事情,我猜这不是故意的。

正如其他人所说,if / then / elif / else可能比&&和{{1}链更清晰}。

测试||有点不清楚,因为它可能意味着很多不同的东西,具体取决于[ $ERRORS ]参数的内容。更明确地表明您只关心它的设置是$ERRORS

[ -n "$ERRORS" ]和朋友这样的比较大多是在shell内置整数运算之前的保留;更现代的习语是[ -ne ]

您的使用消息暗示-a,-e,-g,-w和-y选项采用亚马逊,eBay,Google等形式的参数。该命令的实际语法更清楚没有这些补充;您可以在帮助文本中包含一个额外的段落,列出每个选项代表的内容。

通常,错误消息应该转到stderr而不是stdout((( $# != 2 )))。

使用>&2来保持输出的一致性是很好的,但是单独留下basename $0会有一些说法,因为它会反映用户实际调用的命令。需要考虑的事情。

如果您没有使用格式字符串,那么使用$0并不重要;只需使用printf,它会自动附加换行符。用法消息传统上也不包括引号;用户可以根据是否需要引用arg来引用arg。

检查命令是否成功正是echo的工作原理,因此除非您真正关心确切的退出值,否则无需对if进行明确检查。在你的连接ping的情况下,你可能不关心它失败的原因,只是它做了:

$?

您的搜索查询重新格式化可能需要做的不仅仅是将空格转换为加号;如果它有&符号怎么办?但是,如果你只是做空间到插件的事情,你可以使用bash参数扩展,而不用sed: if ! ping -c 1 209.85.147.103 >/dev/null; then echo >&2 "$0: You are not connected to the Internet!" exit 1 fi

如果你的程序依赖open / xdg-open等,你应该检查它在顶部的可用性;如果您知道无论如何都无法执行所请求的操作,那么就没有意义。并且您可以使用变量,这样您就不会在多个子句中重复自己:

QUERY="${QUERY// /+}"

然后你可以完成这一行:

“$ open”“$ ENGINE = $ QUERY”&> / dev / null

答案 1 :(得分:0)

http://linuxcommand.org/是提高bash脚本技能的绝佳资源。

http://tldp.org/LDP/abs/html/是另一个很棒的文件。

希望这有帮助。