题
我具有相等长度的两个列表,随着单个项目没有空格:
list1="a b c"
list2="1 2 3"
欲遍历并联这两个列表,具有1配对的a,b 2,等:
a 1
b 2
c 3
我试图以支持现代便携式Bourne shell的,所以猛砸/ KSH阵列不可用。脱壳出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
其他提示
大概不会便携式(看看那些庆典-主义!),但它很容易阅读和别人可能会发现它很有用...
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,它需要使用的临时文件。我不知道这是不是调用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
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
没关系,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
有使用普通Unix工具等AWK和切割更优美的方法,但是上面的是作为请求的纯的bash实施
在谈到接受的答案,也没有为我在任何Linux或Solaris工作,问题是在正则表达式中\ S字符类快捷方式的sed。我用[^]代替它和它的工作:
#!/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
作为一个衬里:
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
我张贴这种以防万一有人遇到这个问题的变种,但我根据张贴问题授牌接受的答案。
不隶属于 StackOverflow