在shell脚本中连续循环使用for

时间:2014-02-23 04:52:41

标签: shell

for m in $count
  do
        `cat $op ${arr[$m]} > $op1`
        `rm -f $op`
        `touch $op`
        `cat $op1 ${arr[$m+1]} > $op`
        if [ $m ge $count ]; then
        `rm -f $op1`
        `touch $op1`
        fi
        m=$((m+1))
  done

我想从开始计数2到结束计数10不断循环。这里$ count = 10。但是上面的代码只执行一次for循环。

3 个答案:

答案 0 :(得分:4)

多雨的星期天 - 有很多空闲时间 - 答案很长;)

您的脚本存在许多问题,一些推荐的解决方案。因为您使用了构造m=$((m+1)) - 将使用bash作为“shell”。 (考虑添加bash代码)

对于循环 - 几种可能性

count=10
m=2                           #start with 2
while (( $m <= $count ))      #while m is less or equal to 10
do                            #do
        echo $m               #this action
        let m++               #increment m (add one to m)
done                          #end of while

或者,如果计数是常数(不是变量),则可以写

for m in {2..10}    #REMEMBER, will not works with a variables, like  {2..$count}
do
    echo "$m"
done

另一种变体 - 使用seqman seq)命令进行计数

for m in $(seq 2 ${count:=10})  # ${count:=10} - defaults the $count to 10 if it is undefined
do
    echo $m
done

或C-like for loop

let count=10
for ((m=2; m<=count; m++))
do
        echo $m
done

所有4个循环产生:

2
3
4
5
6
7
8
9
10

所以,现在有一个正确的周期。现在添加您的具体操作。

在:

rm -f $op
touch $op

可以用一个命令替换

echo -n > $op  #echo nothing and write the "nothing" into the file

它更快,因为echobash builtin(不启动两个外部命令)

所以你的行为看起来像是

cat $op ${arr[$m]} > $op1
echo -n > $op
cat $op1 ${arr[$m+1]} > $op

在这种情况下,echo没用,因为第二个cat将写出其输出 反正到$ op(并且在写入之前将文件缩短为零大小),所以这个结果是 与上述相同

cat $op ${arr[$m]} > $op1
cat $op1 ${arr[$m+1]} > $op      

这两个cat命令可以缩短为一个,使用bash的>>附加到文件重定向

cat ${arr[$m]} ${arr[m+1]} >> $op

整个脚本看起来像下一个

#making a testing environment

for f in $(seq 12)               #create 12 files opdata-N 
do
    arr[$f]="opdata-$f"          #store the filenames in the array "arr"
    echo "data-$f" > ${arr[$f]}  #each file contains one line "data-N"
done
#echo ${arr[@]}

#setting the $op and $op1 filenames
#consider choosing more descriptive variable names
op="file_op"
#op1="file_op1"   #not needed

#add some initial (old) value to $op
echo "initial value" > $op
#end of creating the testing environment

#the script
count=10
for m in $(seq 2 $count)
do
    cat ${arr[$m]} ${arr[m+1]} >> $op   
done

最后,文件$op将包含:

initial value
data-2
data-3
data-3
data-4
data-4
data-5
data-5
data-6
data-6
data-7
data-7
data-8
data-8
data-9
data-9
data-10
data-10
data-11
顺便说一句,你确定结果吗?因为如果只想将file-2 .. file-10添加到$op的末尾(不重复条目),您可以简单地写一下:

cat file-{2..10} >> $op    #the '>>' adds to the end of file...

或使用你的数组:

startpos=2
count=10
cat ${arr[@]:$startpos:$count} >> $op   

Ufff ..;)

Ps:通常最好将变量括在双引号中,如"$filename" - 在上面的例子中为了更好的可读性,我省略了它们。

答案 1 :(得分:1)

任何循环都需要“保持循环的条件”。当你使用

for m in count

循环类型,条件是“如果集合count中有更多元素,请选择下一个元素并继续”。这似乎不是你想要的。您正在寻找bash等效的

for(m = 0; m < 10; m++)

我想。这样做的最好方法是 - 正是这种循环(但请注意 - 一对额外的括号和一个分号):

#!/bin/bash
# Display message 5 times
for ((i = 0 ; i < 5 ; i++)); do
  echo "Welcome $i times."
done

see nix craft for original

我认为您可以将此扩展到您的情况......如果我正确理解您的问题,您需要这样的事情:

for ((m = 2; m <= 10; m++))
  do
    cat $op ${arr[$m]} > $op1
    rm -f $op
    touch $op
    cat $op1 ${arr[$m+1]} > $op
    if [ $m ge $count ]; then
      rm -f $op1
      touch $op1
    fi
  done

答案 2 :(得分:0)

改为使用while循环。

for循环是指有多个对象要迭代。你只有一个,即$ count。