Bash,如何迭代一次数组&附加到行尾?

时间:2016-12-08 07:35:46

标签: arrays linux bash append

我的任务是编写一个分析代码的脚本,并附加与#Loop n或#Selection n相对应的正确陈述的评论。

echo "enter full file name: "
read file

getArray(){
  arr=()
  while IFS= read -r line
  do
    arr+=("$line")
  done < "$1"
}

getArray $file

echo "What file looks like before editing"
printf "%s\n" "${arr[@]}" #Test function to see if array works (it does)


#Declare variables
x=1
y=1

#Start main loop
for (( i=0; i<${#arr[@]}; i++ ));
do
  if [[ "${arr[$i]}" == "while" ]] || [[ "${arr[$i]}" == "until" ]]
  then sed -i 's/$/ #Loop'$x'/' $file && let "x++"
       continue
  elif [[ "${arr[$i]}" == "for" ]]
  then sed -i 's/$/ #Loop'$x'/' $file && let "x++"
       continue
  elif [[ "${arr[$i]}" == "break" ]] || [[ "${arr[$i]}" == "done" ]]
  then sed -i 's/$/ #Loop'$x'/' $file && let "x--"
       continue
  elif [[ "${arr[$i]}" == "if" ]] || [[ "${arr[$i]}" == "case" ]]
  then sed -i 's/$/ #Selection'$y'/' $file && let "y++"
       continue
  elif [[ "${arr[$i]}" == "fi" ]] || [[ "${arr[$i]}" == "esac" ]]
  then sed -i 's/$/ #Selection'$y'/' $file && let "y--"
       continue
  else
       continue
  fi
done < $file

显然我是bash的新手,我的循环逻辑/语言用法可能有点不稳定。有人可以帮忙吗?现在输出使得我似乎不止一次遍历数组,并且Sed每行附加额外的文本。

如果不清楚:每个数组元素都是一串字符串;如果数组元素包含while || for || until,那么它会添加#loop n,并且每个对应的breakdone都会添加相同的#loop n。同样适用于ifcase以及fi esac,但会添加#selection n

示例输入:

Before

Final=$(date -d "2016-12-15 14:00" "+%j")
while true ; do
  Today=$(date "+%j")
  Days=$((Final - Today))
  if (( Days >= 14 )) ; then
    echo party
  elif (( Days >= 2 )) ; then
    echo study
  elif (( Days == 1 )) ; then
    for Count in 1 2 3
      do
      echo panic
    done
  else
    break
  fi
  sleep 8h
done

预期产出:

After

Final=$(date -d "2016-12-15 14:00" "+%j")
while true ; do   # loop 1
  Today=$(date "+%j")
  Days=$((Final - Today))
  if (( Days >= 14 )) ; then   # selection 1
    echo party
  elif (( Days >= 2 )) ; then
    echo study
  elif (( Days == 1 )) ; then
    for Count in 1 2 3   # loop 2
      do
      echo panic
    done   # loop 2
  else
    break
  fi   # selection 1
  sleep 8h
done   # loop 1

2 个答案:

答案 0 :(得分:0)

  

现在输出使得我似乎不止一次遍历数组,并且Sed每行附加额外的文本。

这是因为附加到一行的注释会附加到文件的每一行,因为没有为脚本中的sed替换命令指定行号。肯定有更有效的解决方案,但预先填写相应的行号就足够了。

虽然你的脚本非常接近工作,但还有两个问题需要解决。一个是用于测试关键字的==表达式只有在整行包含除关键字以外的任何内容时才匹配(甚至不包括前导空格);为了允许缩进,=~具有适当的正则表达式是有用的。另一个问题是嵌套深度的计数(包括break的简单但特殊的情况,其中深度保持不变);如果我们从深度0开始,这似乎更容易。因此,您的主循环可以是:

x=0
y=0
#Start main loop
for (( i=0; i<${#arr[@]}; i++ ))
do let l=1+i    # line numbers start at 1
  if [[ "${arr[$i]}" =~ ^[$IFS]*(while|until|for) ]]
  then sed -i $l"s/$/ #Loop$((++x))/" $file
  elif [[ "${arr[$i]}" =~ ^[$IFS]*break ]]
  then sed -i $l"s/$/ #Loop$x/" $file # no x-- here!
  elif [[ "${arr[$i]}" =~ ^[$IFS]*done ]]
  then sed -i $l"s/$/ #Loop$((x--))/" $file
  elif [[ "${arr[$i]}" =~ ^[$IFS]*(if|case) ]]
  then sed -i $l"s/$/ #Selection$((++y))/" $file
  elif [[ "${arr[$i]}" =~ ^[$IFS]*(fi|esac) ]]
  then sed -i $l"s/$/ #Selection$((y--))/" $file
  fi
done <$file

答案 1 :(得分:-1)

你可以测试一下;

echo "enter full file name: "
read file

getArray(){
  arr=()
  while IFS= read -r line
  do
    arr+=("$line")
  done < "$1"
}

getArray $file

echo "What file looks like before editing"
printf "%s\n" "${arr[@]}" #Test function to see if array works (it does)


#Declare variables
x=1
y=1

#Start main loop
for (( i=0; i<${#arr[@]}; i++ ));
do
    #echo $i "====" ${arr[$i]}
    #echo "-------"
    #echo "x"$x
  if [[ "${arr[$i]}" == "while"* ]] || [[ "${arr[$i]}" == "until" ]]
  then 
       sed -i "$((i+1))s/$/ #Loop $x/" $file 
       let "x++"
       continue; 
   fi

  if [[ "${arr[$i]}" == *"for"* ]]
  then sed -i "$((i+1))s/$/ #Loop'$x'/" $file && let "x++"
       continue
   fi

  if [[ "${arr[$i]}" == *"done"* ]]
  then sed -i "$((i+1))s/$/ #Loop'$((x-1))'/" $file 
       continue
   fi

  if [[ "${arr[$i]}" == *"if"* ]] || [[ "${arr[$i]}" == *"case"* ]]
  then 
        if [[ "${arr[$i]}" != *"elif"* ]] 
        then 
            sed -i "$((i+1))s/$/ #Selection'$y'/" $file && let "y++"
        fi
        continue
       fi
  if [[ "${arr[$i]}" == *"fi"* ]] || [[ "${arr[$i]}" == *"esac"* ]]
  then sed -i "$((i+1))s/$/ #Selection'$((y-1))'/" $file
       continue
  fi


done < $file