bash for ループの最後の反復決定

bash for ループの最後の反復決定

設定ファイルにいくつかの行を追加するループがあります。

for i in ${H//,/ }
do
        sed -i "7i\                      host($i) or" $configPath/$g.conf
done

$ Hはコンマ区切りの変数です(例:host1、host2、host4、host10)。

次を返します。

                  host(host10) or
                  host(host4) or
                  host(host2) or
                  host(host1) or

しかし、私が達成したいのは次のとおりです。

                  host(host10) or
                  host(host4) or
                  host(host2) or
                  host(host1)

またはその逆も:

                  host(host1) or
                  host(host2) or
                  host(host4) or
                  host(host10)

私がこれを行う方法の正しい方向を見つけるのを助けることができる人はいますか?

答え1

この問題は、ほとんどのプログラミング言語で同じ形式で発生します。何とかサフィックスをスキップするのは複雑です。私はシェル構文について議論しません。人々が一般的にこの問題にどのようにアクセスするかについての疑似コードの概要だけを説明します。

# get it over with at the beginning:
print a[0] (no newline)
loop from a[1] onwards:
   print "or\n"
   print a[i]
print "\n" #terminate the last one

この場合、インデックステストは含まれていないため(言語がbashやPythonなどの配列の直接反復をサポートしている場合)、インデックスを繰り返すか、すべての要素を繰り返し(最初の要素をスキップするように)動作します。できます。

0から始めて最後の項目をスキップしてループの外で処理することもできます(上のミラーを参照)、最後の項目をスキップすることは通常汚れて不可能です(最後の項目をスキップするには最後の項目であることに注意してください。)はいつでもすぐにスキップできます。ストリームから要素を読み込み、どの要素が最後の要素であるかが事前にわからない場合、この形式は唯一のオプションです。

別の方法:

# test a loop counter
N = length of array
loop with indices:
   if i==N-1:
      print a[i]
   else:
      print a[i],"or"

この場合、要素の数を知る必要があり、インデックスを継続的にテストします。したがって、インデックスを繰り返すか、インデックスを個別に追跡する必要があります(ループの前にi = 0を設定し、ループ内にi ++を設定)。

私はこれをレシピで書いており、bashの実装はあなたに任せます。

答え2

私が見るには、コードを少し変更するだけです。最初のループで空の変数に「or」を入れます。

operator=''
for i in ${H//,/ }
do
        sed -i "7i\                      host($i)$operator" "$configPath/$g.conf"
        operator=' or'
done

答え3

通常、テキスト処理にシェルループを使用したくありません。ここでは以下を使用しますawk

export H
awk 'NR == 7 {
  s = ENVIRON["H"]
  gsub(/,/, ") or\n   host(", s)
  print "   host(" s ")"}
  {print}' file

GNUに内部編集オプションがsedあるように、GNU(4.1.0以降)にも同等のオプションとして1があります。-iawk-i /usr/share/awk/inplace.awk

テキストファイルを編集するには、テキストエディタを使用する必要があると思うかもしれません。使用vim:

export H
vim -esc '
  let @a=$H
  6put a
  s/.*/host(&)/
  s/,/) or\rhost(/g
  x' file

^使用しないでください-i inplace現在の作業ディレクトリから最初に拡張機能をgawkロードしようとすると、誰かがそのディレクトリにマルウェアを植えた可能性があります。システムに付属の拡張プログラムのパスは異なる場合があります。出力を参照してください。inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

答え4

元の質問で「sed」を使用する代わりに、アイデアを説明するためにechoを使用してより簡単な質問を作成しました。スペースで区切られた項目を繰り返す代わりに:

  • まず、繰り返し回数を決定するために、"、"置換後の単語数を取得します。
  • "()"を使用して空の文字列を配列に変換する
  • 繰り返し回数
  • 「または」部分を条件の出力に取り込み、変数に入れます。
  • 繰り返しによる配列サブセット
  • echo/sedなどもあります。

    #!/bin/bash
    
    H="host1,host2,host3"
    H2=${H//,/ }
    N=`echo $H2 | wc -w`
    H3=($H2)
    
    for ((i = 1; i <= $N; i++))
    do
        if [ "$i" -eq "$N" ]; then OR=""; else OR=" or"; fi
        ITEM=${H3[$i-1]}
        echo "$ITEM$OR"
    done
    

関連情報