web-dev-qa-db-ja.com

シェルスクリプトの単一のforループで複数の変数をどのように使用できますか?

以下のコードをforループを使用して実装していますが、スクリプトの実行後に誤った出力が表示されます。

for i in `awk -F"|" '{print $1}' $INPUTFILE`, j in `awk -F"|" '{print $2}' $INPUTFILE`
do
echo $i:$j
done  

シェルスクリプトの単一のforループで複数の変数を使用するのを手伝ってください。

8
user3548033

bashは複数の変数を持つループを許可しますが、Cのような構文でのみ可能です。

for ((i=0,j=10;i<=j;i++,j--))
do
   echo "i=$i"
   echo "j=$j"
done
12
Dani_l

多分あなたは実際に欲しい:

while IFS='|' read -r i j rest <&3; do
  {
    printf '%s\n' "something with $i and $j"
  } 3<&-
done 3< "$INPUTFILE"

しかし、 Shellループを使用してテキストを処理することは、多くの場合、間違った方法です

ここでは、必要なように聞こえます:

awk -F '|' '{print $1 ":" $2}' < "$INPUTFILE"

タイトルの質問への回答として、forループが複数の変数を取得するシェルの場合、zshが得られます(引用符を付けないことで、すでにzsh構文を使用しているようです)変数、またはコマンド置換を分割するときにグロビングを無効にしない):

$ for i j in {1..6}; do echo $i:$j; done
1:2
3:4
5:6

または短い形式:

for i j ({1..6}) echo $i:$j

POSIXシェルと同等:

set -- 1 2 3 4 5 6
## or:
# IFS='
# ' # split on newline
# set -f # disable globbing
# set -- $(awk ...) # split the output of awk or other command
while [ "$#" -gt 0 ]; do
  echo "$1:$2"
  shift 2
done
11

ファイルの出力を変数に格納して、それを2つに分割できます。例:

in exampleファイルの内容は次のとおりです。

a:1
b:2
c:3
d:4

今スクリプト。

#!/bin/bash
for n in $(cat example)
do
    first=$(echo $n | cut -d ":" -f 1)
    second=$(echo $n | cut -d ":" -f 2)
    echo $first
    echo $second
done
2
Bikash Shaw

組み込みシステムでは、何が利用可能であるかが足りないことがよくあります。例えば。 forは1つの変数のみを持つことができます。 awkprintfは単に利用できません。またはIFSはサポートされていません。等.

これらの状況では、次のような目標を達成できます。

export i=xxx
for j in `cat INPUTFILE` ; do \
    [ $i == xxx ] && export i=$j && continue ; \
    echo "$i:$j" ; \
    export i=xxx ; \
done
unset i

このソリューションのより一般的な形式は次のようになります。

export A=xxx
export B=xxx
for i in 1 2 3 4 5 6 7 8 9 10 11 ; do \
    [ $A == xxx ] && export A=$i && continue ; \
    [ $B == xxx ] && export B=$i && continue ; \
    echo "$A:$B:$i" ; \
    export A=xxx ; \
    export B=xxx ; \
done
unset A
unset B
  • 文字列「xxx」がデータセットに表示されないものと想定します...表示する/する可能性がある場合は、別の文字列を選択します。
  • 「レコード」ごとに任意の数の「フィールド」を持つことができます...フィールド{A、B、...}を処理するFOUR行のそれぞれを複製するだけです。
  • 最後のフィールドは常に$ iと呼ばれます... export C=$i役立つ場合はechoの直前。
  • データセット内の文字列の数がレコードサイズの倍数でない場合、「残り」(つまり、| set |%| record |)は失われます。
1
BlueChip

多くの場合、GNU Parallelはこの解決策となります。

parallel -a $INPUTFILE --colsep '|' echo {1}:{2}
0
Ole Tange

_for i in 1 2 3; do for j in a b c; do ...; done; done_のように複数の変数を反復処理する場合は、複数のループが必要です。繰り返す対象のリストが別のコマンドの出力である場合、その別のコマンドを$()でラップする必要があります。