为什么我的shell脚本在第二次尝试失败?

Jac*_*out 3 bash darwin getopts

此脚本应接受一组搜索字词,并返回格式化的网址以搜索Google.

$ ./google_search.sh albert einstein
https://www.google.com/search?q=albert+einstein
Run Code Online (Sandbox Code Playgroud)

它做得很好,所以我决定添加一个选项来搜索特定网站,或者使用-s-S标记忽略该网站.

$ ./google_search.sh -s wikipedia.org albert einstein
https://www.google.com/search?q=albert+einstein+site%3Awikipedia.org
Run Code Online (Sandbox Code Playgroud)

这在您第一次运行脚本时有效,但在每次后续尝试时都会失败.

$ ./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
Run Code Online (Sandbox Code Playgroud)

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

剧本:

#!/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
Run Code Online (Sandbox Code Playgroud)

需要更改什么才能使此脚本更可靠?

Vau*_*ato 5

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

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