Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何改进此脚本?_Bash_Shell - Fatal编程技术网

Bash 如何改进此脚本?

Bash 如何改进此脚本?,bash,shell,Bash,Shell,我正在学习shell脚本,发现很难找到一个好的学习方法。我在下面创建了一个脚本,它允许用户通过选项搜索各种不同的互联网引擎。如果有人能看穿这一点,指出我做错了什么,如何改进,等等,我将不胜感激 #!/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_no

我正在学习shell脚本,发现很难找到一个好的学习方法。我在下面创建了一个脚本,它允许用户通过选项搜索各种不同的互联网引擎。如果有人能看穿这一点,指出我做错了什么,如何改进,等等,我将不胜感激

#!/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
提前谢谢大家,意义重大

是提高bash脚本编写技能的绝佳资源

这是另一个伟大的文件


希望这能有所帮助。

最好在codereviews中发布,如上所述,但这里有一些主要的风格评论。我要强调的是,剧本很好;这些只是一些小的改进,我认为这将有助于使代码更易于阅读/维护,在一些情况下更健壮,等等

您不需要仅仅因为环境变量都是大写而对变量名使用所有大写;shell变量和环境变量不是一回事

由于您的
$OPTIONS
变量一次只保存一个选项,因此最好使用单数名称(例如
$option
)。或者您可以选择
$opt
,这在这里有点传统

getopts字符串(
aegwy:
)中的
表示
-y
选项需要一个参数,如
-y
中的某个参数,而不仅仅是
-y
。既然您没有使用
$OPTARG
做任何事情,我猜这不是故意的

正如其他人所说,一个
如果
/
那么
/
elif
/
否则
可能比
&
|
的链条更清晰

测试
[$ERRORS]
有些不清楚,因为根据
$ERRORS
参数的内容,它可能意味着许多不同的事情。一个更明确的指示是,您只关心是否设置了它,
[-n“$ERRORS”]

[-ne]
和friends这样的比较大多是在shell内置整数算法之前留下的;更现代的成语应该是
($#!=2))

您的用法消息意味着-a、-e、-g、-w和-y选项采用亚马逊、易趣、谷歌等形式的参数。如果不添加这些参数,命令的实际语法将更加清晰;您可以在帮助文本中添加一个额外的段落,列出每个选项的含义

通常,错误消息应该转到stderr而不是stdout(
&2

可以使用
basename$0
来保持输出的一致性,但是要说的是不要使用
$0
,因为这将反映用户实际调用命令的方式。需要考虑的事情。< /P> 如果不使用格式字符串,则使用
printf
没有多大意义;只需使用
echo
,它会自动添加换行符。使用信息传统上也不包括引号;用户是否引用arg取决于是否需要

如果工作,则检查命令是否成功正是
的工作方式,因此无需对
$?
进行显式检查,除非您真正关心确切的退出值。在连接ping的情况下,您可能不关心它失败的原因,只关心它失败了:

  if ! ping -c 1 209.85.147.103 >/dev/null; then 
     echo >&2 "$0: You are not connected to the Internet!"
     exit 1
  fi
您的搜索查询重新格式化可能需要做的不仅仅是将空格变成加号;如果它有一个符号怎么办?但是,如果您只是在执行空格到加号的操作,那么可以使用bash参数扩展,而不使用sed:
QUERY=“${QUERY///+}”

如果您的程序依赖于open/xdg open等,您可能应该在顶部检查其可用性;如果您知道自己无论如何都不可能执行请求的操作,那么做任何其他事情都没有意义。您可以使用一个变量,这样就不会在多个子句中重复自己:

open=
for cmd in open xdg-open; do
   if type -p "$cmd" >/dev/null; then
     open="$cmd"
     break
   fi
done
if [ -z "$open" ]; then
   echo >&2 "$0: open command not found."
   exit 1
fi
然后你可以用这一行来结束:


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

它是否按预期工作?“代码>……& &……/代码>有点难读,也许可以考虑使用<代码>如果。除此之外,这似乎还可以…它工作得很好,但我不知道是否有更好的方法,谢谢你的回答。一位大师可能会想出一些办法,但这看起来是对的。您的
y
选项看起来需要一个值,
[…]和&
的内容将更易于阅读,因为
if[…]
,但在其他方面它看起来很好。我现在可能会改为if语句,您认为y选项需要一个值是什么意思?再次感谢这类问题更适合解释为什么这个答案被否决。最初的海报上写着“我正在学习shell脚本,很难找到一个好的学习方法。”这些都是值得学习的优秀资源。因此,如果这不是一个好的答案,我想知道为什么。只有几个链接的答案是不鼓励的;这可能是一个评论。撇开这个问题在StackOverflow上有点离题不谈,海报要求对他们的代码发表评论,而不仅仅是编程指南的链接。顺便说一句,我不是反对者:)不幸的是,我还不能添加评论,所以回答问题是目前提供反馈的唯一方式。只要你提供几个正确的主题答案或提出一些有趣的问题,这种情况就会改变:你需要评论。我建议在此期间不要发表类似评论的回答:人们会在不考虑你是否可以发表评论的情况下否决投票。祝你好运:)另外,请参阅上的本指南。非常感谢你提供了极其详细的答案。这肯定会让你受益匪浅。我特别喜欢参数展开,它比使用sed容易得多。再次感谢!