脚本:
#!/bin/bash
IFS=','
i=0
for j in `cat database | head -n 1`; do
variables[$i]=$j
i=`expr $i + 1`
done
k=0
for l in `cat database | tail -n $(expr $(cat database | wc -l) - 1)`; do
echo -n $k
k=`expr $k + 1`
if [ $k -eq 3 ]; then
k=0
fi
done
输入文件
a,b,c
d,e,f
g,e,f
输出
01201
预期输出
012012
问题是为什么跳过最后的回声?这很奇怪,因为如果我将$ k更改为$ l,则echo将运行6次。
答案 0 :(得分:2)
<强>更新强>:
@ thom的分析是正确的。您可以通过将IFS=','
更改为IFS=$',\n'
来解决问题。
我在下面的原始陈述可能具有普遍意义,但不解决具体问题 如果意外的shell扩展是一个问题,这里是如何重写循环(假设首先将所有内容读入数组变量是实用的):
IFS=$',\n' read -d '' -r -a fields < <(echo $'*,b,c\nd,e,f\ng,h,i')
for field in "${fields[@]}"; do
# $field is '*' in 1st iteration, then 'b', 'c', 'd',...
done
原始陈述:
只是一些一般性的指示:
您应该使用while
循环而不是for
来读取命令输出 - 请参阅http://mywiki.wooledge.org/BashFAQ/001;缺点:使用for
,输入行可以进行各种shell扩展。
缺少迭代通常源于最后一个输入行缺少终止\n
(或$IFS
中定义的分隔符)。使用while
循环,您可以使用以下方法解决此问题:while read -r line || [[ -n $line ]]; do …
例如,您的第二个for
循环可以重写为(使用进程替换作为输入以避免创建具有单独变量范围的子shell):
while read -r l || [[ -n $l ]]; do …; done < <(cat database | tail -n $(expr $(cat database | wc -l) - 1))
最后,您可以从使用现代基础知识中受益:例如,
k=`expr $k + 1`
可以更简洁地重写为(( ++k ))
(也会更快地运行)。
答案 1 :(得分:2)
您的代码在每个读取变量之后都需要逗号,但您只能这样:
a,b,c
d,e,f
g,e,f
而不是:
a,b,c,
d,e,f,
g,e,f,
所以它写着:
d,e,f'\n'g,e,f
并且等于5个值,而不是6个