繁体   English   中英

Bash,如何遍历数组一次并追加到行尾?

[英]Bash, how to iterate through an array once & append to end of line?

我的任务是编写一个脚本,该脚本分析代码并使用与正确语句相对应的#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 while || for || until 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

现在,输出使我好像遍历数组不止一次,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

您可以对此进行测试;

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM