使用subshel​​l和substring打击坏替换

Mat*_*att 19 string bash substitution subshell

一个人为的例子......给出了

FOO="/foo/bar/baz"
Run Code Online (Sandbox Code Playgroud)

这工作(在bash中)

BAR=$(basename $FOO) # result is BAR="baz"
BAZ=${BAR:0:1}       # result is BAZ="b"
Run Code Online (Sandbox Code Playgroud)

这不

BAZ=${$(basename $FOO):0:1} # result is bad substitution
Run Code Online (Sandbox Code Playgroud)

我的问题是哪个规则导致这个[子shell替换]评估不正确?如果有的话,在1跳中执行此操作的正确方法是什么?

Dan*_*tin 11

首先,请注意,当你这样说:

BAR=$(basename $FOO) # result is BAR="baz"
BAZ=${BAR:0:1}       # result is BAZ="b"
Run Code Online (Sandbox Code Playgroud)

在构建第一位BAZIS 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.
Run Code Online (Sandbox Code Playgroud)

然后稍后:

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

稍后,当它定义您要询问的语法时:

   ${parameter:offset:length}
          Substring Expansion.  Expands to  up  to  length  characters  of
          parameter  starting  at  the  character specified by offset.
Run Code Online (Sandbox Code Playgroud)

因此,联机帮助页中阐明的规则表明${foo:x:y}构造必须具有参数作为第一部分,并且参数只能是名称,数字或少数特殊参数字符之一.$(basename $FOO)不是参数允许的可能性之一.

至于在一个赋值中执行此操作的方法,请使用管道到其他响应中提到的其他命令.


jil*_*les 6

修改形式的参数替换,例如${parameter#word}只能修改参数,而不能修改任意字.

在这种情况下,您可能会将输出basename传递给dd命令,例如

BAR=$(basename -- "$FOO" | dd bs=1 count=1 2>/dev/null)
Run Code Online (Sandbox Code Playgroud)

(如果你想要更高的计数,增加count而不是bs,否则你可能会得到比请求更少的字节.)

在一般情况下,在一项任务中无法做到这样的事情.


小智 6

它失败了,因为它${BAR:0:1}是一个可变扩展.Bash希望看到后面的变量名${,而不是值.

我不知道在单个表达式中做到这一点的方法.