2.7.1. Linux Shell学习心得

  1. 递归函数中的变量值被下层调用所修改的问题

    由于Linux shell中默认定义的变量都是全局的,所以导致在递归函数中定义的变量,在下一层调用中修改了值后,返回上一层,改变量已被修改,导致运行结果不对。

    解决办法就是,给相应的变量加上local前缀,表示是局部变量,即可。

    详情参看:【已解决】Linux Shell中,递归函数调用过程中,变量的值被改变,即下层调用会影响上层中的变量的值

  2. ./xxx.sh: line xx: [: too many arguments

    问题原因:参数太多

    比如,使用

    if [ -d $item_full_path ]; then

    去判断item_full_path是否为文件夹,但是如果传入的参数是

    arm_vs_mips.xml - Copy_bak

    ,则会出现too many arguments的错误。因为对于shell中的-d去判断一个参数是否为文件夹的时候,此参数,只能是一个字符串,而不能是多个字符串,而此处的

    arm_vs_mips.xml - Copy_bak

    虽然物理上表示对应的某个文件,但是作为此处的参数传递进来的话,的确就是三个字符串了:

    arm_vs_mips.xml
    -
    Copy_bak
                    

    解决办法:自己去找错误的位置,是不是也是由于类似的,使用某个功能的时候,传递的参数,超过该功能所期望的参数的个数了。如果超过了,估计多数情况下,也都是你自己使用不当,或者没有进行合适的处理而导致的。

  3. 文件名中包含空格的问题

    在用shell过程中,经常会遇到处理文件名中包含空格的问题

    对此,参考Linux shell脚本 遍历带空格的文件名,尝试了用tr将ls输出结果替换为问号,的确是可以的:

    CLi@PC-CLI-1 ~/develop/docbook/books/arm_vs_mips/src
    $ ls
    arm_vs_mips.xml      arm_vs_mips_____xml - Copy_bak    glossary.xml  Makefile       remove_bak.sh
    arm_vs_mips.xml.bak  ch01_reduced_instruction_set.xml  images        reference.xml  remove_bak.sh.bak
    
    CLi@PC-CLI-1 ~/develop/docbook/books/arm_vs_mips/src
    $ ls | tr " " "\?"
    arm_vs_mips.xml
    arm_vs_mips.xml.bak
    arm_vs_mips_____xml?-?Copy_bak
    ch01_reduced_instruction_set.xml
    glossary.xml
    images
    Makefile
    reference.xml
    remove_bak.sh
    remove_bak.sh.bak
                    
    [提示]cygwin中的tr在shell中工作不正常? -> 实际上是cygwin中的显示有问题

    不过,另外提及一下,目前遇到一个问题,就是上述的代码:

    ls | tr " " "\?"

    放到shell中执行:

    local sub_folders=`ls $input_folder | tr "\32" "\?"`;
    echo '444 sub_folders='$sub_folders;
                            

    当时结果是tr无效,输出的效果中文件名中的空格没有被替换为问号。

    其中当前环境是用的Cygwin,tr版本为:

    CLi@PC-CLI-1 ~/develop/docbook/books/arm_vs_mips/src
    $ tr --version
    tr (GNU coreutils) 8.15
    Packaged by Cygwin (8.15-1)
    Copyright (C) 2012 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    Written by Jim Meyering.
                            

    后来终于经过一番折腾,而搞清楚了:

    把问号换成其他的,比如<,>等:

    local sub_folders=`ls $input_folder | tr "\32" "\<"`;
    local sub_folders=`ls $input_folder | tr "\32" "\>"`;
                            

    也都是可以看到替换的结果的。

    并且也可以用:

    each_item=`echo $each_item | tr "\<" " "`;
    each_item=`echo $each_item | tr "\>" " "`;
                            

    再替换回来的。

    而对于上述的问号替换空格,虽然没有显示出来,但是如果没有此操作的话,后面

    for each_item in $sub_folders; do

    所得到的每个item中,

    arm_vs_mips.xml - Copy_bak

    就会变成三个字符串:

    arm_vs_mips.xml
    -
    Copy_bak
                        

    而有此操作,后面得到的就是一个独立的字符串:

    arm_vs_mips.xml - Copy_bak

    所以明白了根本原因是,Cygwin中,没有正确的显示出来,实际上,是已经替换成功的了。

    不过很悲催的是,单独echo问号字符,却又是可以正常显示的。。。

    说实话,这样的bug,真的很让人崩溃。。。太浪费时间了。。。