質問

私は、個々のアイテムでスペースを入れずに、同じ長さの二つのリストを持っています:

list1="a b c"
list2="1 2 3"

私はなど、2とB、1とのペアリング、並行してこれら二つのリストを反復処理したい:ます。

a 1
b 2
c 3

私はバッシュ/ kshの配列は使用できませんので、現代のポータブルBourneシェルをサポートしようとしています。 AWKに砲撃してピンチに受け入れられるだろうが、可能であれば私はむしろ純粋なSHでこれを維持すると思います。

あなたが提供することができます任意のポインタをありがとう!

役に立ちましたか?

解決

これは少しハックですが、仕事をしていません。

#!/bin/sh
list1="1 2 3"
list2="a b c"
while [ -n "$list1" ]
do
    head1=`echo "$list1" | cut -d ' ' -f 1`
    list1=`echo "$list1" | sed 's/[^ ]* *\(.*\)$/\1/'`
    head2=`echo "$list2" | cut -d ' ' -f 1`
    list2=`echo "$list2" | sed 's/[^ ]* *\(.*\)$/\1/'`
    echo $head1 $head2
done

他のヒント

(すべてのそれらのbash-ISMSを見てください!)

おそらく移植性がありませんが、読みやすいですし、他の誰かがそれに便利...

見つけるかもしれません
list1="a b c"
list2="1 2 3"
array1=($list1)
array2=($list2)

count=${#array1[@]}
for i in `seq 1 $count`
do
    echo ${array1[$i-1]} ${array2[$i-1]}
done

これはかなりきれいな解決策になるはずですが、あなたはbashのプロセスsubstitionを使用しない限り、それは一時ファイルを使用する必要があります。それは各反復上cutsedを呼び出すよりも良いか悪いかどうかは分かりません。

#!/bin/sh

list1="1 2 3"
list2="a b c"
echo $list1 | sed 's/ /\n/g' > /tmp/a.$$
echo $list2 | sed 's/ /\n/g' > /tmp/b.$$

paste /tmp/a.$$ /tmp/b.$$ | while read item1 item2; do
    echo $item1 - $item2
done

rm /tmp/a.$$
rm /tmp/b.$$

これはポータブルでも二つ以上のリストで動作する必要があります:

#!/bin/sh
x="1 2 3 4 5"
y="a b c d e"
z="A B C D E"

while
    read current_x x <<EOF
$x
EOF

    read current_y y <<EOF
$y
EOF

    read current_z z <<EOF
$z
EOF

    [ -n "$current_x" ]
do
    echo "x=$current_x y=$current_y z=$current_z"
done

あまりにも、位置paramersの作品を使用しました。 「 - 」リスト要素がで始めることはできませんのでご注意ください。それ以外の場合は、 "設定" 失敗します。

#!/bin/sh

x="1 2 3 4 5"
y="a b c d e"
z="A B C D E" 

while
    [ -n "$x" ]
do
    set $x
    current_x=$1
    shift
    x="$*"

    set $y
    current_y=$1
    shift
    y="$*"

    set $z
    current_z=$1
    shift
    z="$*"

    echo "x=$current_x y=$current_y z=$current_z"
done

NEVERMINDは、SAW "ボーン" とは、 "AGAINボーン" と思いました。それは尋ねた質問への答え誰かのために有用であることが、はっきりしない場合がありますので、ここではこれを残して、申し訳ありません!

-

このは(それが優雅にサイズが異なるリストを処理しません)、いくつかの欠点がありますが、それはあなたが与えた例のために働くます:

#!/bin/bash

list1="a b c"
list2="1 2 3"

c=0
for i in $list1
do
  l1[$c]=$i
  c=$(($c+1))
done

c=0
for i in $list2
do
  echo ${l1[$c]} $i
  c=$(($c+1))
done

そこのawkやカットなどの一般的なUNIXツールを使用して、より優雅な方法がありますが、上記の要求に応じて、純粋な-bashの実装です。

受け入れ答えにコメント、それはLinuxまたはSolarisのいずれかで私のために動作しませんでした、問題はsedのための正規表現で\ S文字クラスのショートカットでした。私は[^]でそれを置き換え、それが働いた:

#!/bin/sh
list1="1 2 3"
list2="a b c"
while [ -n "$list1" ]
do
    head1=`echo "$list1" | cut -d ' ' -f 1`
    list1=`echo "$list1" | sed 's/[^ ]* *\(.*\)$/\1/'`
    head2=`echo "$list2" | cut -d ' ' -f 1`
    list2=`echo "$list2" | sed 's/[^ ]* *\(.*\)$/\1/'`
    echo $head1 $head2
done

配列を使用していないソリューション:

list1="aaa1 aaa2 aaa3"
list2="bbb1 bbb2 bbb3"

tmpfile1=$( mktemp /tmp/list.XXXXXXXXXX ) || exit 1
tmpfile2=$( mktemp /tmp/list.XXXXXXXXXX ) || exit 1

echo $list1 | tr ' ' '\n'  > $tmpfile1
echo $list2 | tr ' ' '\n'  > $tmpfile2

paste  $tmpfile1  $tmpfile2

rm --force $tmpfile1  $tmpfile2

1つのライナーとして:

list2="1 2 3"; 
list1="a b c"; 
for i in $list1; do 
    x=`expr index "$list2" " "`; 
    [ $x -eq 0 ] && j=$list2 || j=${list2:0:$x}; 
    list2=${list2:$x}; 
    echo "$i $j"; 
done
$ list1="1 2 3"
$ list2="a b c"
$ echo "$list1 $list2" | awk '{n=NF/2; for (i=1;i<=n;i++) print $i,$(n+i) }'
1 a
2 b
3 c
最初のソリューションはここまで示し始めたときに

私は、sedのベースの答えに取り組んでいました。

:しかし、さらに調査すると、それは私が頭と尾に基づくソリューションで行くことを許され、リスト内の項目は改行ではなくスペースで区切ったことが判明しました
original_revs="$(cd original && git rev-parse --all)" &&
working_revs="$(cd working && git rev-parse --all)" &&
while test -n "$original_revs"; do
    original_commit="$(echo "$original_revs" | head -n 1)" &&
    working_commit="$(echo "$working_revs" | head -n 1)" &&
    original_revs="$(echo "$original_revs" | tail -n +2)" &&
    working_revs="$(echo "$working_revs" | tail -n +2)" &&
    ...
done

私は、誰かがこの問題の変種に遭遇しただけの場合にこれを掲示していますが、私は掲載され問題に基づいて受け入れ答えを授与しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top