在Bash中,`${1#*=}`是什么意思?

5

我在StackOverflow上找到了一篇很棒的答案,它解释了如何将关联数组传递给一个函数。有人能帮我弄清楚下面代码中${1#*=}的语法是什么吗?(摘自那个答案,作者为jaypal singh):

#!/bin/bash

declare -A weapons=(
  ['Straight Sword']=75
  ['Tainted Dagger']=54
  ['Imperial Sword']=90
  ['Edged Shuriken']=25
)

function print_array {
    eval "declare -A arg_array="${1#*=}
    for i in "${!arg_array[@]}"; do
       printf "%s\t%s\n" "$i ==> ${arg_array[$i]}"
    done
}

print_array "$(declare -p weapons)"

以下是我的猜测(如果我对其中任何一项有误,请纠正):
- 1 表示传递给函数的第一个参数($1${1}
- # 表示 $1 的索引,由于 $1 是一个关联数组,所以 #$1 的键
- * 表示关联数组 $1 中与 # 键对应的值

那么剩下的 = 是什么意思?那是不是表示您希望 #* 分别指代关联数组的键和值呢?

2
仅供记录,应指出此解决方案不安全,并允许函数从参数字符串执行任意代码。 - Etan Reisner
2个回答

12

片段 ${1#*=} 与关联数组无关。*(Bash的语法非常一致,一点也不令人困惑)

这是对函数或脚本的第一个参数(${1})值的模式匹配。其语法为

${variable#glob}

其中

  • variable是任何bash变量
  • glob是要与之匹配的任何通配符模式(受到 pathname expansion 的限制)

它删除从行的开头开始的最短匹配。 还有##,它从变量的开头删除最长匹配,%从结尾删除最短匹配,%%则从结尾删除最长匹配。


例如,以下代码:

myVar="abc=llamas&disclaimer=true"
echo "${myVar#*=}"

它会将llamas&disclaimer=true打印到屏幕上。

另一方面,

myVar="abc=llamas&disclaimer=true"
echo ${myVar##*=}

将会打印true,并且

myVar="foobar is bad"
echo "${myVar%%b*}"

将打印foo


* 在bash man页面中有详细说明;只需搜索字符串${parameter#word}即可找到它。


1
这很奇怪:一个完美的答案却完全弄错了。#%不会获取指定的glob,它们是在删除它。${myvar # * =}将从示例值中删除abc=并打印其余部分。我把它归为那种意图非常明确,以至于人们甚至没有注意到自己正在做出更正的错误。 - jthill
@jthill 您的意思是我交换了 #% 吗?老实说,每次我坐在终端使用其中之一时都会这样做。我已经放弃尝试记住它了。希望我没有造成太大的损失。 - jpaugh
不,我的意思是:它们不会获取匹配的内容,而是剥离它。 echo ${myvar#*=} 剥离到第一个 = 并打印其余部分。 - jthill
@jthill 好的,现在我明白了。谢谢!当然你是对的;但我总是用它们来“抓取”,并且可能会继续把它们看作“抓取”运算符。 :-/ - jpaugh

6
它会删除由模式*=匹配的字符串(从开头开始的最短匹配),并将其从由$1评估的字符串中删除。

$1是传递给shell的第一个位置参数

常规格式也可以写成${var#patt},其中在$var中匹配(从开头开始的最短匹配),然后删除patt

示例:

var="first=middle=last"
echo "${var#*=}"

输出:

middle=last

如果使用${var##pat}而不是${var#pat},则从开头匹配最长的pat

例如:

var="first=middle=last"
echo "${var##*=}"

输出:

last


来自Bash手册

${parameter#word}

${parameter##word}

单词会被扩展成一个模式,就像文件名扩展一样(见文件名扩展)。如果模式匹配参数的扩展值的开头,那么展开结果是参数的扩展值中,最短匹配模式(‘#’情况)或最长匹配模式(‘##’情况)删除后得到的。如果参数是“@”或“*”,则模式移除操作会分别应用于每个位置参数,并且展开结果是生成的列表。如果参数是带有“@”或“*”下标的数组变量,则模式删除操作将依次应用于数组的每个成员,并且展开结果是生成的列表。


1
手册链接:http://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion - Etan Reisner
1
啊,参数扩展居然没想到!这很有道理。谢谢! - GreenRaccoon23

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接