一个人为的例子......给出了
FOO="/foo/bar/baz"
这有效(在bash中)
BAR=$(basename $FOO) # result is BAR="baz"
BAZ=${BAR:0:1} # result is BAZ="b"
这不是
BAZ=${$(basename $FOO):0:1} # result is bad substitution
我的问题是哪个规则导致此[子shell替换]评估错误?如果有的话,在1跳中执行此操作的正确方法是什么?
答案 0 :(得分:11)
首先请注意,当你这样说时:
BAR=$(basename $FOO) # result is BAR="baz"
BAZ=${BAR:0:1} # result is BAZ="b"
BAZ
的构造中的第一位是BAR
而不是值,您想要获取第一个字符。因此,即使bash允许变量名包含任意字符,第二个表达式中的结果也不是您想要的结果。
但是,关于阻止这种情况的规则,请允许我引用bash手册页:
DEFINITIONS
The following definitions are used throughout the rest of this docu‐
ment.
blank A space or tab.
word A sequence of characters considered as a single unit by the
shell. Also known as a token.
name A word consisting only of alphanumeric characters and under‐
scores, and beginning with an alphabetic character or an under‐
score. Also referred to as an identifier.
稍后:
PARAMETERS
A parameter is an entity that stores values. It can be a name, a num‐
ber, or one of the special characters listed below under Special Param‐
eters. A variable is a parameter denoted by a name. A variable has a
value and zero or more attributes. Attributes are assigned using the
declare builtin command (see declare below in SHELL BUILTIN COMMANDS).
以后它定义了你要问的语法:
${parameter:offset:length}
Substring Expansion. Expands to up to length characters of
parameter starting at the character specified by offset.
因此,联机帮助页中阐明的规则说${foo:x:y}
构造必须有一个参数作为第一部分,并且参数只能是名称,数字或少数特殊参数字符之一。 $(basename $FOO)
不是参数允许的可能性之一。
至于在一个作业中执行此操作的方法,请使用管道到其他响应中提到的其他命令。
答案 1 :(得分:6)
参数替换的修改形式(例如${parameter#word}
)只能修改参数,而不能修改任意单词。
在这种情况下,您可以将basename
的输出传递给dd命令,例如
BAR=$(basename -- "$FOO" | dd bs=1 count=1 2>/dev/null)
(如果您想要更高的计数,请增加count
而不是bs
,否则您可能会获得比请求更少的字节数。)
在一般情况下,在一项任务中无法做到这样的事情。
答案 2 :(得分:6)
失败是因为${BAR:0:1}
是变量扩展。 Bash希望在${
之后看到变量名,而不是值。
我不知道在单个表达式中做到这一点的方法。
答案 3 :(得分:1)
正如其他人所说,$ {}的第一个参数需要是一个变量名。但是你可以使用另一个子shell来估计你想要做的事情。
而不是:
BAZ=${$(basename $FOO):0:1} # result is bad substitution
使用:
BAZ=$(_TMP=$(basename $FOO);${_TMP:0:1}) # this works
答案 4 :(得分:0)
$ {string:0:1},字符串必须是变量名
例如:
FOO = “/富/酒吧/ baz” 的
巴兹= “foo” 的
BAZ = eval echo '${'"$(basename $FOO)"':0:1}'
结果是'f'
答案 5 :(得分:0)
为您的人为例子设计的解决方案:
BAZ=$(expr $(basename $FOO) : '\(.\)')
,如
$ FOO=/abc/def/ghi/jkl
$ BAZ=$(expr $(basename $FOO) : '\(.\)')
$ echo $BAZ
j