【问题标题】:Why does my shell script fail on second attempt?为什么我的 shell 脚本在第二次尝试时失败?
【发布时间】:2012-12-06 15:41:30
【问题描述】:

这个脚本应该接受一组搜索词并返回一个格式化的 URL 来搜索 google。

$ ./google_search.sh albert einstein
https://www.google.com/search?q=albert+einstein

这样做很好,所以我决定添加一个选项来搜索特定站点,或者忽略该站点,使用 -s-S 标志。

$ ./google_search.sh -s wikipedia.org albert einstein
https://www.google.com/search?q=albert+einstein+site%3Awikipedia.org

这在您第一次运行脚本时有效,但在随后的每次尝试中都会失败。

$ ./google_search.sh -s wikipedia.org albert einstein
https://www.google.com/search?q=albert+einstein
$ ./google_search.sh -s wikipedia.org albert einstein
https://www.google.com/search?q=albert+einstein

打开一个新的终端窗口或重新启动终端都可以清除此问题并允许在失败之前再尝试一次。

脚本:

#!/bin/bash

# original source of concatenate_args function by Tyilo:
# http://stackoverflow.com/questions/9354847/concatenate-inputs-in-bash-script
function concatenate_args
{
    string=""
    ignorenext=0
    for a in "$@" # Loop over arguments
    do
        if [[ "${a:0:1}" != "-" && $ignorenext = 0 ]] # Ignore flags (first character is -)
        then
            if [[ "$string" != "" ]]
            then
                string+="+" # Delimeter
            fi
            string+="$a"
        elif [[ $ignorenext = 1 ]]
        then
            ignorenext=0
        else
            ignorenext=1
        fi
    done
    echo "$string"
}

qry="$(concatenate_args "$@")"
glink="https://www.google.com/search?q="

site=""
while getopts :s:S: opt; do
    case $opt in
        s) site="+site%3A$OPTARG" ;; 
        S) site="+-site%3A$OPTARG" ;; 
    esac
done

url=$glink$qry$site

echo $url
# open -a Firefox $url

需要进行哪些更改才能使此脚本更可靠?

【问题讨论】:

  • -xv 选项添加到 shebang 行以查看发生了什么。
  • 这似乎没有任何作用。我正在尝试#!/bin/bash -xv
  • 这表现得好像您正在采购脚本而不是执行它。您确定您使用的是./google_search.sh 而不是. google_search.sh?试试bash google_search.sh
  • 或者,您正在编辑脚本的不同副本。
  • 如果脚本是可执行的,只需删除点并使用alias google=/Tools/google_search.sh。如果没有,请使用alias google='bash /Tools/google_search.sh'

标签: bash darwin getopts


【解决方案1】:

这就像您在获取脚本而不是执行它一样。如果在脚本前使用点和空格,则会导致脚本在当前 shell 内逐行执行,而不是创建新的 shell。这允许在脚本内更改的环境变量泄漏到您当前的 shell 环境中,这可能会使脚本的一次运行与下一次运行不同。

在这种情况下,它似乎是使用 getopts。 getopts 每次调用时都会更新一个环境变量,以便它可以跟踪正在检查的参数。第二次获取脚本时,它认为所有参数都已经检查过了,所以你的参数最终被忽略了。

【讨论】:

  • 您刚刚回答了我接下来要问的问题,“当脚本被‘采购’时会发生什么不同?”我会花大量时间学习应该如何使用它。再次感谢!
【解决方案2】:

您的脚本,简化:

#!/bin/bash
glink="https://www.google.com/search?q="
site=""

# if you're "source"ing, uncomment the following:
# OPTIND=1

while getopts :s:S: opt; do
    case $opt in
        s) site="+site:$OPTARG" ;; 
        S) site="+-site:$OPTARG" ;; 
        ?) echo "invalid option: -$OPTARG" >&2 ;;
    esac
done
shift $((OPTIND - 1))
# the positional parameters are now clear of "-s" and "-S" options

qry=$(IFS="+"; echo "$*")
url=$glink$qry$site
echo "$url"
# open -a Firefox "$url"

【讨论】:

    猜你喜欢
    • 2015-10-11
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 2012-05-25
    • 2019-09-07
    • 1970-01-01
    相关资源
    最近更新 更多