如何从bash CGI脚本解析$ QUERY_STRING

Use*_*er1 20 bash cgi

我有一个正在CGI中使用的bash脚本.CGI通过读取$QUERY_STRINGURL中的所有内容来设置$ QUERY_STRING环境变量.例如,http://example.com?a = 123&b = 456&c = ok设置?.

在某处我发现了以下丑陋:

QUERY_STRING=a=123&b=456&c=ok

将$ b设置为$ QUERY_STRING中找到的任何内容b=$(echo "$QUERY_STRING" | sed -n 's/^.*b=\([^&]*\).*$/\1/p' | sed "s/%20/ /g").但是,我的脚本已经增长到超过十个输入参数.有没有更简单的方法将$ QUERY_STRING中的参数自动转换为bash可用的环境变量?

也许我只会使用某种类型的for循环,但如果脚本足够智能以自动检测每个参数并且可能构建一个类似于以下内容的数组,那就更好了:

${parm[a]}=123
${parm[b]}=456
${parm[c]}=ok
Run Code Online (Sandbox Code Playgroud)

我怎么能写代码呢?

Pau*_*ce. 41

试试这个:

saveIFS=$IFS
IFS='=&'
parm=($QUERY_STRING)
IFS=$saveIFS
Run Code Online (Sandbox Code Playgroud)

现在你有了这个:

parm[0]=a
parm[1]=123
parm[2]=b
parm[3]=456
parm[4]=c
parm[5]=ok
Run Code Online (Sandbox Code Playgroud)

在具有关联数组的Bash 4中,您可以执行此操作(使用上面创建的数组):

declare -A array
for ((i=0; i<${#parm[@]}; i+=2))
do
    array[${parm[i]}]=${parm[i+1]}
done
Run Code Online (Sandbox Code Playgroud)

哪个会给你这个:

array[a]=123
array[b]=456
array[c]=ok
Run Code Online (Sandbox Code Playgroud)

编辑:

在Bash 2及更高版本中使用间接(使用parm上面创建的数组):

for ((i=0; i<${#parm[@]}; i+=2))
do
    declare var_${parm[i]}=${parm[i+1]}
done
Run Code Online (Sandbox Code Playgroud)

然后你将有:

var_a=123
var_b=456
var_c=ok
Run Code Online (Sandbox Code Playgroud)

您可以直接访问这些:

echo $var_a
Run Code Online (Sandbox Code Playgroud)

或间接地:

for p in a b c
do
    name="var$p"
    echo ${!name}
done
Run Code Online (Sandbox Code Playgroud)

如果可能的话,最好避免间接,因为它会使代码变得混乱并成为bug的来源.

  • +1 用于`parm` 数组生成。但是所有用于循环该数组的方法都无法正确处理重复的键。每次出现都会覆盖前一次。例如,a=1&amp;a=2&amp;a=x 将导致 parm[a]=x (2认同)
  • `parm=($QUERY_STRING)` 将 `$QUERY` 扩展产生的词置于 globbing 中,这可能是不受欢迎的。一个更强大的替代方案,也可以省去保存和恢复 `$IFS` 的麻烦: `IFS='&amp;=' read -ra parm &lt;&lt;&lt;"$QUERY_STRING"` 最好不要使用全大写的 shell 变量名为了[避免与环境变量和特殊shell变量冲突](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_01)。 (2认同)

gho*_*g74 15

你可以分解$QUERY使用IFS.例如,将其设置为&

$ QUERY="a=123&b=456&c=ok"
$ echo $QUERY
a=123&b=456&c=ok
$ IFS="&"
$ set -- $QUERY
$ echo $1
a=123
$ echo $2
b=456
$ echo $3
c=ok

$ array=($@)

$ for i in "${array[@]}"; do IFS="=" ; set -- $i; echo $1 $2; done
a 123
b 456
c ok
Run Code Online (Sandbox Code Playgroud)

你可以保存为Bash 4+中的哈希/字典

$ declare -A hash
$ for i in "${array[@]}"; do IFS="=" ; set -- $i; hash[$1]=$2; done
$ echo ${hash["b"]}
456
Run Code Online (Sandbox Code Playgroud)

  • +1为set-$ var`把戏..非常整洁;) (2认同)

小智 6

请不要使用邪恶的评估垃圾。

下面是如何可靠地解析字符串并获得关联数组的方法:

declare -A param   
while IFS='=' read -r -d '&' key value && [[ -n "$key" ]]; do
    param["$key"]=$value
done <<<"${QUERY_STRING}&"
Run Code Online (Sandbox Code Playgroud)

如果你不喜欢密钥检查,你可以这样做:

declare -A param   
while IFS='=' read -r -d '&' key value; do
    param["$key"]=$value
done <<<"${QUERY_STRING:+"${QUERY_STRING}&"}"
Run Code Online (Sandbox Code Playgroud)

列出数组中的所有键和值:

for key in "${!param[@]}"; do
    echo "$key: ${param[$key]}"
done
Run Code Online (Sandbox Code Playgroud)