11

同じ長さのリストが2つあり、個々のアイテムにスペースはありません。

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

これらの2つのリストを並行して繰り返し、aと1、bと2などをペアにします。

a 1
b 2
c 3

最新のポータブルBourneシェルをサポートしようとしているため、Bash/kshアレイは使用できません。awkに砲撃することはピンチで許容されますが、可能であれば、これを純粋なshで維持したいと思います。

あなたが提供できるどんなポインタにも感謝します!

4

9 に答える 9

15

おそらく移植性はありませんが (これらの 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
于 2009-02-13T18:19:04.490 に答える
5

これはかなりクリーンなソリューションになるはずですが、bashのプロセス置換を使用しない限り、一時ファイルを使用する必要があります。cutそれが呼び出しとsedすべての反復よりも良いか悪いかはわかりません。

#!/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.$$
于 2009-02-13T18:24:41.653 に答える
4

これは少しハックですが、仕事をします:

#!/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
于 2009-02-13T18:00:22.633 に答える
3

これは移植性があり、2 つ以上のリストでも機能する必要があります。

#!/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

位置パラメータの使用も機能します。リスト要素は「-」で始まらない場合があることに注意してください。それ以外の場合、「設定」は失敗します。

#!/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
于 2015-01-25T13:11:34.730 に答える
1

最初のソリューションがここに表示され始めたとき、私は 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

誰かがこの問題の変種に遭遇した場合に備えてこれを投稿していますが、投稿された問題に基づいて受け入れられた回答を授与しています.

于 2009-02-14T00:57:13.833 に答える
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
于 2009-02-13T18:18:10.390 に答える
1

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

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
于 2009-02-13T18:28:37.947 に答える
1
$ 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
于 2012-10-26T01:17:45.800 に答える
1

NEVERMIND、「BOURNE」を見て「BOURNE 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 や cut などの一般的な 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
于 2009-02-13T17:55:01.243 に答える