【问题标题】:Store parameter into variable with space用空格将参数存储到变量中
【发布时间】:2017-04-19 12:00:08
【问题描述】:

考虑以下带有输出的命令:

$ du -sm ~/Documents 
458 /home/utilisateur/Documents
$ du -sm ~/Documents --exclude='aa bb' --exclude='cc dd'
153 /home/utilisateur/Documents

我希望用这样一个变量替换排除项,以获得相同的输出。

$ du -sm ~/Documents "$c"

但是,如果我使用以下设置变量,我失败了。我测试了:

$ c=--exclude='aa bb'\ --exclude='cc dd'
$ du -sm ~/Documents "$c"
458 /home/utilisateur/Documents

$ c="\"--exclude='aa bb' --exclude='cc dd'\""
$ du -sm ~/Documents $c
458 /home/utilisateur/Documents
du: cannot access '"--exclude='\''aa': No such file or directory
du: cannot access 'bb'\''': No such file or directory
du: cannot access 'dd'\''"': No such file or directory

$ c="--exclude='aa bb' --exclude='cc dd'"
$ du -sm ~/Documents "$c"
458 /home/utilisateur/Documents
$ du -sm ~/Documents $c
458 /home/utilisateur/Documents
du: cannot access 'bb'\''': No such file or directory
du: cannot access 'dd'\''': No such file or directory

请帮我改正我的错误。我知道这是关于引号的。

【问题讨论】:

    标签: bash variables quotes


    【解决方案1】:
    du --exclude='aa bb' --exclude='cc dd'
    

    您有多个参数,其中至少有一些包含空格。 没有办法将它们放在单个字符串变量中,以便保留参数之间的分隔。

    如果你这样做了

    args="--exclude=aa bb --exclude=cc dd"
    du $args
    

    字符串在所有空格上拆分,为du 提供四个不同的参数: --exclude=aabb--exclude=ccdd

    另一方面,与

    du "$args"
    

    args 的内容根本没有被分割,所以du 得到一个参数。

    引号没有帮助,因为它们在扩展变量后没有被处理,但它们会按字面意思转到命令,正如您从 du 给出的错误中看到的那样。

    正确的解决方法是使用an array:

    args=("--exclude=aa bb" "--exclude=cc dd")   # initialize it
    args+=("--exclude=ee ff")                    # you can even append to it
    du -sm ~/Documents "${args[@]}"
    

    另请参阅:Why does my shell script choke on whitespace or other special characters? on unix.SE

    【讨论】:

    • 所以,数组是关键!此外,args=(--exclude='aa bb' --exclude='cc dd') 也可以使用。谢谢ikkachu!
    • @NicolasSmith,是的,-a="foo bar""-a=foo bar"-a=foo\ bar-a=foo" "bar 完全相同。 IOW,只要空格被引用,其余的都没有关系,因为没有任何其他特殊字符。从shell的角度来看,等号并不特殊
    【解决方案2】:

    如果您在脚本中使用它,请将您的变量放在引号中:

    du -sm "$path" "$exc"
    

    同样将exc的赋值改为

    exc="--exclude=aa bb" 
    

    另一个选择是更改Internal Field Separator。只需像这样将其设置为换行符(记住在完成后恢复其原始值):

    OLDIFS="$IFS"
    IFS="
    "
    # do your scripting stuff
    # restore IFS
    IFS="$OLDIFS"
    

    编辑:如果您使用多个--exclude,这将不起作用。

    【讨论】:

    • 我更新了我的问题,因为有几个--exclude 需要和相同的问题。你能帮我吗?
    • 如果要将引号传递给命令,则引用引号有效。通常你不会。另外,我看不出更改 IFS 在这里有什么帮助?
    • @ilkkachu 我的答案是脚本(我真的没有提到,所以我的错),因此IFS。同样在我回答之后,OP 将他的问题更改为包含两个 --exclude 语句,然后它停止工作。你的回答很好,所以 +1 :)
    猜你喜欢
    • 1970-01-01
    • 2015-01-12
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多