如何将文件单行含空格的元素读取到Bash数组?
Bash从单行文件读取带空格的数组元素解决方案
问题描述
测试代码尝试从单行文件读取带空格的元素到数组,但所有尝试的方法都无法像直接定义数组ARRAY_1那样,将含空格的内容作为单个元素,而是被错误分割成多个元素。
测试代码
#!/bin/bash # Declare array with 4 elements # ARRAY_1=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux ) # Contents of ARRAY_1 # echo ARRAY_1: ${ARRAY_1[@]} # Get number of elements in the array # NUM_ELEMENTS=${#ARRAY_1[@]} # echo each element in array # for (( i=0;i<$NUM_ELEMENTS;i++ )); do echo ${ARRAY_1[${i}]} done echo echo Now try with reading from a file. echo The goal is to behave like ARRAY_1 echo Note: Its important that all the elements appear echo on one line in the file. echo tmpFile=/tmp/TEST_ELEMENTS.$$ cat << EOF > $tmpFile 'Debian Linux' 'Redhat Linux' Ubuntu Linux EOF # How to get this to behave like ARRAY_1 assignment above? # # ARRAY_2=( `eval "cat $tmpFile"` ) # Nope. # ARRAY_2=( $(cat $tmpFile) ) # Also Nope # ARRAY_2=( $(xargs < $tmpFile) ) # Also Nope declare -a ARRAY_2=( $(xargs < $tmpFile) ) # Also Nope echo ARRAY_2: ${ARRAY_2[@]} NUM_ELEMENTS=${#ARRAY_2[@]} for (( i=0;i<$NUM_ELEMENTS;i++ )); do echo ${ARRAY_2[${i}]} done /bin/rm $tmpFile
错误输出
ARRAY_1: Debian Linux Redhat Linux Ubuntu Linux Debian Linux Redhat Linux Ubuntu Linux Now try with reading from a file. The goal is to behave like ARRAY_1 Note: Its important that all the elements appear on one line in the file. ARRAY_2: Debian Linux Redhat Linux Ubuntu Linux Debian Linux Redhat Linux Ubuntu Linux
解决方案
核心问题是直接使用$(cat $tmpFile)这类方式时,Bash会先进行分词,把单引号当成普通字符处理,导致带空格的元素被拆分。正确的做法是利用eval重新解析文件内容的引号结构,让Bash识别带空格的元素为单个数组项。
修改后的数组赋值代码如下:
# 正确的赋值方式 eval "ARRAY_2=( $(cat "$tmpFile") )"
完整修正后的代码
#!/bin/bash # Declare array with 4 elements # ARRAY_1=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux ) # Contents of ARRAY_1 # echo ARRAY_1: ${ARRAY_1[@]} # Get number of elements in the array # NUM_ELEMENTS=${#ARRAY_1[@]} # echo each element in array # for (( i=0;i<$NUM_ELEMENTS;i++ )); do echo ${ARRAY_1[${i}]} done echo echo Now try with reading from a file. echo The goal is to behave like ARRAY_1 echo Note: Its important that all the elements appear echo on one line in the file. echo tmpFile=/tmp/TEST_ELEMENTS.$$ cat << EOF > $tmpFile 'Debian Linux' 'Redhat Linux' Ubuntu Linux EOF # 正确的赋值方式 eval "ARRAY_2=( $(cat "$tmpFile") )" echo ARRAY_2: ${ARRAY_2[@]} NUM_ELEMENTS=${#ARRAY_2[@]} for (( i=0;i<$NUM_ELEMENTS;i++ )); do echo ${ARRAY_2[${i}]} done /bin/rm $tmpFile
正确输出
ARRAY_1: Debian Linux Redhat Linux Ubuntu Linux Debian Linux Redhat Linux Ubuntu Linux Now try with reading from a file. The goal is to behave like ARRAY_1 Note: Its important that all the elements appear on one line in the file. ARRAY_2: Debian Linux Redhat Linux Ubuntu Linux Debian Linux Redhat Linux Ubuntu Linux
原理说明
$(cat "$tmpFile")读取文件内容后,会保留原始的引号结构;eval会让Bash重新解析整个赋值语句,识别单引号作为字符串边界,从而将'Debian Linux'这类带空格的内容视为单个数组元素,而非拆分后的两个元素。
内容的提问来源于stack exchange,提问作者James Rowell
相关产品推荐
相关产品推荐

