代码之家  ›  专栏  ›  技术社区  ›  ʞɔıu

在bash中为循环中的…处理特殊字符

  •  3
  • ʞɔıu  · 技术社区  · 15 年前

    file1
    "file 1"
    file2
    

    for…in循环在空白处而不是换行符之间将其拆分:

    for x in $( ls ); do
       echo $x
    done
    

    结果:

    file
    1
    file1
    file2
    

    这比我认为find-print0 | xargs-0能够处理的要复杂一些,因为我实际上希望命令类似于“convert-input/file1.jpg….output/file1.jpg”,所以我需要在这个过程中排列文件名。

    3 回复  |  直到 15 年前
        1
  •  9
  •   plan9assembler    15 年前

    事实上,马克的建议很有效,甚至不需要对内部字段分隔符做任何操作。问题是在子shell中运行ls,无论是通过backticks还是$(),都会导致for循环无法区分名称中的空格。简单使用

    for f in *
    

    而不是ls解决了这个问题。

    #!/bin/bash
    for f in *
    do
     echo "$f"
    done
    
        2
  •  2
  •   eduffy    9 年前

    由OP更新

    一种可能的方式:

    ls -1 | while read x; do
       echo $x
    done
    

        3
  •  0
  •   Richard T    15 年前

    我知道这是一个早已过去的“回答”,并充分尊重爱德华菲,我想出了一个更好的方法,我想我会分享它。

    eduffy答案的“错误”并不在于它是错误的,而是它强加了一个对我来说是痛苦的限制:当ls的输出通过管道传输时,隐含地创建了一个子shell,这意味着在循环中设置的变量在循环退出后丢失。因此,如果你想写一些更复杂的代码,你就有麻烦了。

    我的解决方案是采用“阅读线” 作用

    ls_output=$(ls -1)
    # The cut at the end of the following line removes any trailing new line character
    declare -i line_count=$(echo "$ls_output" | wc -l | cut -d ' ' -f 1)
    declare -i cur_line=1 
    while [ $cur_line -le $line_count ] ;
    do  
       # NONE of the values in the variables inside this do loop are trapped here.
       filename=$(echo "$ls_output" | readline -n $cur_line)
       # Now line contains a filename from the preceeding ls command
       cur_line=cur_line+1
    done
    

    现在,您已经将所有的子shell活动打包到了整洁的小包中,并且可以进行shell编码,而不必担心变量值的范围被困在子shell中。

    我用gnuc写了我的readline版本如果有人想要一个副本,在这里发布有点大,但也许我们可以找到一种方法。。。

    RT