我具有相等长度的两个列表,随着单个项目没有空格:

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,它需要使用的临时文件。我不知道这是不是调用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

没关系,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

我张贴这种以防万一有人遇到这个问题的变种,但我根据张贴问题授牌接受的答案。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top