Arrays 为什么我的bashshell脚本在v3.2.5上运行而在4.1.2上失败?
我的bashshell脚本正在bash3.2.5上运行。 我有一个包含以下内容的输入文件:Arrays 为什么我的bashshell脚本在v3.2.5上运行而在4.1.2上失败?,arrays,linux,bash,shell,Arrays,Linux,Bash,Shell,我的bashshell脚本正在bash3.2.5上运行。 我有一个包含以下内容的输入文件: 1234567 2345678 3456789 4567890 以及具有以下代码的bash shell脚本: #!/bin/bash content=($(cat data.txt | awk {'print $1'})) for (( i=0 ; i<${#content[@]} ; i++ )) do if (( i==0 )) then ele=`echo ${content
1234567
2345678
3456789
4567890
以及具有以下代码的bash shell脚本:
#!/bin/bash
content=($(cat data.txt | awk {'print $1'}))
for (( i=0 ; i<${#content[@]} ; i++ ))
do
if (( i==0 ))
then
ele=`echo ${content[$i]}`
else
ele=`echo ","${content[$i]}`
fi
all=`echo $all$ele`
done
# should be a string of csv: works on bash 3.2.5 - fails on bash 4.1.2
echo $all
但是当使用bash4.1.2运行时,它会输出:(文件中的最后一个数字;不正确)
为什么Bash 4.1.2中的代码失败了?使用
echo
设置变量的内容很简单。。错。当我说错的时候,我的意思是,你可以这样做,但是绝对没有理由在这种情况下使用echo
语句的命令替换来填充变量。同样,没有理由使用管道连接到awk
的cat
来填充数组。只需一个简单的重定向,填充数组就容易多了
通过消除echo
和piped
命令的所有不必要的命令替换
,您消除了许多出错的机会。这里有一个可以在3或4上使用的更新
#!/bin/bash
content=( $( <data.txt) )
for (( i=0 ; i<${#content[@]} ; i++ ))
do
if (( i==0 ))
then
ele="${content[i]}"
else
ele=",${content[i]}"
fi
all="${all}${ele}"
done
echo $all
使用echo
设置变量的内容很简单。。错。当我说错的时候,我的意思是,你可以这样做,但是绝对没有理由在这种情况下使用echo
语句的命令替换来填充变量。同样,没有理由使用管道连接到awk
的cat
来填充数组。只需一个简单的重定向,填充数组就容易多了
通过消除echo
和piped
命令的所有不必要的命令替换
,您消除了许多出错的机会。这里有一个可以在3或4上使用的更新
#!/bin/bash
content=( $( <data.txt) )
for (( i=0 ; i<${#content[@]} ; i++ ))
do
if (( i==0 ))
then
ele="${content[i]}"
else
ele=",${content[i]}"
fi
all="${all}${ele}"
done
echo $all
这无助于理解您看到的症状,但您的代码可以完全重写为
paste -d , -s data.txt
如果要使用bash构造,请执行以下操作:
mapfile -t numbers < data.txt # read the lines of the file into an array
(IFS=,; echo "${numbers[*]}") # join the array with a comma
mapfile-t numbers
但是,请检查您的数据文件是否不包含回车:oc-d data.txt
,然后使用dos2unix
或sed-i的/\r$/'data.txt
这无助于理解您看到的症状,但您的代码可以按照以下方式完全重写:
paste -d , -s data.txt
如果要使用bash构造,请执行以下操作:
mapfile -t numbers < data.txt # read the lines of the file into an array
(IFS=,; echo "${numbers[*]}") # join the array with a comma
mapfile-t numbers
但是,请检查您的数据文件是否不包含回车:oc-d data.txt
,并使用dos2unix
或sed-i的/\r$/'data.txt
将显著注释转换为答案
这些作业包括:
ele=`echo ","${content[$i]}"`
all=`echo $all$ele`
不应使用反勾号`…`
或$(…)
命令替换;你应该写得简单些
all="$all$sep${content[$i]}"
其中,您可以在循环之前有sep=“”
,在分配给所有人之后有sep=“,”
另外,FWIW,我在Mac OS X 10.10.2上尝试了Bash版本3.2.57(1)和4.3.27(2)的脚本,我得到了与这两个版本相同的正确(预期)输出
- 你看过bash-xyourscript.sh发生了什么吗?这是一种基本且非常重要的shell脚本调试技术
- 您是否检查了数据文件中的Windows样式CRLF行尾?
当我的data.txt
文件有Windows风格的CRLF(回车,换行)行结尾时,我得到了“Bash 4.1.2”输出。当我的data.txt
文件有Unix风格的NL(换行符,又称换行符)行结尾时,我得到了“Bash 3.2.5”输出
您是否通过Windows系统将材料复制到运行Bash 4.1.2的机器上?或者,换句话说,您确定在测试它的两台机器上运行的数据文件完全相同吗
我会将脚本简化为:
sep=""
all=""
while read number
do
all="$all$sep$number"
sep=","
done < data.txt
echo "$all"
sep=“”
all=“”
读数字时
做
all=“$all$sep$number”
sep=“,”
done
还有其他方法可以达到同样的效果,但这是非常直接的,并且不使用任何子shell,这与原始脚本使用大量子shell不同。将显著的注释转换为答案
这些作业包括:
ele=`echo ","${content[$i]}"`
all=`echo $all$ele`
不应使用反勾号`…`
或$(…)
命令替换;你应该写得简单些
all="$all$sep${content[$i]}"
其中,您可以在循环之前有sep=“”
,在分配给所有人之后有sep=“,”
另外,FWIW,我在Mac OS X 10.10.2上尝试了Bash版本3.2.57(1)和4.3.27(2)的脚本,我得到了与这两个版本相同的正确(预期)输出
- 你看过bash-xyourscript.sh发生了什么吗?这是一种基本且非常重要的shell脚本调试技术
- 您是否检查了数据文件中的Windows样式CRLF行尾?
当我的data.txt
文件有Windows风格的CRLF(回车,换行)行结尾时,我得到了“Bash 4.1.2”输出。当我的data.txt
文件有Unix风格的NL(换行符,又称换行符)行结尾时,我得到了“Bash 3.2.5”输出
您是否通过Windows系统将材料复制到运行Bash 4.1.2的机器上?或者,换句话说,您确定在测试它的两台机器上运行的数据文件完全相同吗
我会将脚本简化为:
sep=""
all=""
while read number
do
all="$all$sep$number"
sep=","
done < data.txt
echo "$all"
sep=“”
all=“”
读数字时
做
all=“$all$sep$number”
sep=“,”
done
还有其他方法可以达到同样的效果,但这非常简单,并且不使用任何子shell,这与原始脚本使用大量子shell不同。这个问题的答案是;由于4.1.2上运行的脚本使用的文件中存在crlf
乔纳森L