Bash使用子shell和子字符串进行错误替换
一个人为的例子。。。给定Bash使用子shell和子字符串进行错误替换,bash,string,substitution,subshell,Bash,String,Substitution,Subshell,一个人为的例子。。。给定 FOO="/foo/bar/baz" 这是有效的(在bash中) 这并不重要 BAZ=${$(basename $FOO):0:1} # result is bad substitution 我的问题是,哪条规则导致[子shell替换]的计算不正确?如果有正确的方法,在一跳中做这件事的正确方法是什么?修改过的参数替换形式,如${parameter#word}只能修改一个参数,不能修改任意单词 在这种情况下,您可以通过管道将basename的输出传输到dd命令,如 B
FOO="/foo/bar/baz"
这是有效的(在bash中)
这并不重要
BAZ=${$(basename $FOO):0:1} # result is bad substitution
我的问题是,哪条规则导致[子shell替换]的计算不正确?如果有正确的方法,在一跳中做这件事的正确方法是什么?修改过的参数替换形式,如
${parameter#word}
只能修改一个参数,不能修改任意单词
在这种情况下,您可以通过管道将basename
的输出传输到dd命令,如
BAR=$(basename -- "$FOO" | dd bs=1 count=1 2>/dev/null)
(如果您想要更高的计数,请增加count
而不是bs
,否则您得到的字节可能比请求的字节少。)
在一般情况下,没有办法在一次赋值中执行类似操作。它失败,因为
${BAR:0:1}
是一个变量展开。Bash希望在${
之后看到一个变量名,而不是一个值
我不知道如何在一个表达式中实现它。首先,请注意,当您这样说时:
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)
不是参数允许的可能性之一
至于在一个赋值中执行此操作的方法,请使用管道到其他响应中提到的其他命令。${string:0:1},string必须是变量名 例如: FOO=“/FOO/bar/baz” baz=“foo” BAZ=
eval echo'${'$(basename$FOO)“':0:1}'
echo$BAZ
结果是“f”正如其他人所说,${}的第一个参数需要是一个变量名。但是您可以使用另一个子shell来近似您要做的事情 而不是:
BAZ=${$(basename $FOO):0:1} # result is bad substitution
使用:
针对您的人为示例的人为解决方案:
BAZ=$(expr $(basename $FOO) : '\(.\)')
如
BAZ=$(_TMP=$(basename $FOO); echo ${_TMP:0:1}) # this works
BAZ=$(expr $(basename $FOO) : '\(.\)')
$ FOO=/abc/def/ghi/jkl
$ BAZ=$(expr $(basename $FOO) : '\(.\)')
$ echo $BAZ
j