【问题标题】:How can I handle an array where elements contain spaces in Bash?如何处理 Bash 中元素包含空格的数组?
【发布时间】:2016-02-28 19:55:59
【问题描述】:

假设我有一个名为 tmp.out 的文件,其中包含以下内容:

c:\My files\testing\more files\stuff\test.exe
c:\testing\files here\less files\less stuff\mytest.exe

我想将该文件的内容放入一个数组中,我这样做:

ARRAY=( `cat tmp.out` )

然后我通过这样的 for 循环运行它

for i in ${ARRAY[@]};do echo ${i}; done

但是输出最终是这样的:

c:\My
files\testing\more
files\stuff\test.sas
c:\testing\files
here\less
files\less
stuff\mytest.sas

我希望输出是:

c:\My files\testing\more files\stuff\test.exe
c:\testing\files here\less files\less stuff\mytest.exe

我该如何解决这个问题?

【问题讨论】:

  • 对于您的简化问题,您可以避免使用数组并将@choroba 的循环与echo "${line}" 一起使用。我希望您可以在没有数组的情况下为更复杂的现实生活任务实现解决方案!

标签: arrays bash for-loop


【解决方案1】:

您可以使用 IFS 变量,即内部字段分隔符。将其设置为空字符串以仅在换行符上拆分内容:

while IFS= read -r line ; do
    ARRAY+=("$line")
done < tmp.out

-r 需要保留文字反斜杠。

【讨论】:

  • IFS 用于内部行空白。你不需要它。尽管IFS= 确实希望将其设置为空白,以防止多个空格的分词折叠运行。
  • 对于 bash 4+ 来说,mapfileBash FAQ 005 更好。
  • @chepner:这个反应与我之前的回复有关,这确实是错误的。
  • Bash 没有read -a ARRAY 用于读取数组吗?
  • @JonathanLeffler:read -a A 将从标准输入的一行中取出的单个单词放入数组Amapfile -t A 将标准输入中的各行放入数组中。
【解决方案2】:

为了遍历数组中的值,你需要引用数组扩展以避免分词:

for i in "${values[@]}"; do 

当然,你也应该引用值的使用:

  echo "${i}"
done

这并没有首先回答如何将文件的行放入数组的问题。如果你有 bash 4.0,你可以使用 mapfile 内置:

mapfile -t values < tmp.out

否则,您需要临时将 IFS 的值更改为单个换行符,或在 read 内置函数上使用循环。

【讨论】:

    【解决方案3】:

    控制分词的另一种简单方法是控制内部字段分隔符 (IFS):

    #!/bin/bash
    
    oifs="$IFS"  ## save original IFS
    IFS=$'\n'    ## set IFS to break on newline
    
    array=( $( <dat/2lines.txt ) )  ## read lines into array
    
    IFS="$oifs"  ## restore original IFS
    
    for ((i = 0; i < ${#array[@]}; i++)) do
        printf "array[$i] : '%s'\n" "${array[i]}"
    done
    

    输入

    $ cat dat/2lines.txt
    c:\My files\testing\more files\stuff\test.exe
    c:\testing\files here\less files\less stuff\mytest.exe
    

    输出

    $ bash arrayss.sh
    array[0] : 'c:\My files\testing\more files\stuff\test.exe'
    array[1] : 'c:\testing\files here\less files\less stuff\mytest.exe'
    

    【讨论】:

    • 在子shell中分配一个shell变量并没有多大用处。
    • @rici - 这种情况下的解决方案是将进程移出子shell。固定。
    • 除非您关闭 shell globbing,否则仅包含 * 的行将被替换为文件名列表。
    • 鉴于示例输入,我没有考虑到这一点,但这是一个非常有效的观点。因此,如果数据有可能出现这种情况,我们需要在将文件重定向到数组之前使用set -f,然后使用set +f
    猜你喜欢
    • 2015-05-13
    • 2020-07-23
    • 2012-02-23
    • 2021-01-24
    • 2017-10-28
    • 2013-02-19
    • 1970-01-01
    • 2011-08-26
    • 2013-08-06
    相关资源
    最近更新 更多