同じ長さのリストが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で維持したいと思います。
あなたが提供できるどんなポインタにも感謝します!
おそらく移植性はありませんが (これらの 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のプロセス置換を使用しない限り、一時ファイルを使用する必要があります。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.$$
これは少しハックですが、仕事をします:
#!/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
これは移植性があり、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
最初のソリューションがここに表示され始めたとき、私は 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
誰かがこの問題の変種に遭遇した場合に備えてこれを投稿していますが、投稿された問題に基づいて受け入れられた回答を授与しています.
ワンライナーとして:
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="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
$ 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
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