操作数预期 - Shell While循环

时间:2018-03-05 02:01:57

标签: bash shell sorting while-loop

大家好,我试图在shell中冒泡排序,但我得到一个操作数预期错误。我初始化了我需要使用的变量,并确保我使用正确的语法(如果我没有,请纠正我)。我得到的错误是在这一行:

X = $ {阵列[$ i]于}

谢谢

traces | project timestamp, datetime_part('microsecond', timestamp)

2 个答案:

答案 0 :(得分:2)

在这个脚本中有很多地方你可以通过足够的语法来完成与你想要的完全不同的事情。为了演示这些问题,让我初始化几个变量:

$ array=(15 22 30 93 27)
$ i=2

好的,第一个问题命令是echo $array。这只打印数组的第一个元素;要打印其所有元素,请使用echo "${array[@]}"。请注意,我在它周围添加了双引号 - 围绕变量引用的双引号几乎总是一个好主意,以避免单词拆分和通配符扩展的意外影响。当我说“好主意”时,我的意思是“如果你不这样做,当你测试它时,它可能会完美地工作,然后一段时间后会出现一个奇怪的错误,你将不知道是什么继续,直到你将问题跟踪到一个应该被双引号的变量引用。双引号变量引用只是很好的脚本卫生。无论如何,这是一个错误的阵列打印的快速演示:

$ echo $array    # wrong
15
$ echo "${array[@]}"    # right
15 22 30 93 27

其次,在while [ $j -lt ${#array[@]-1} ]中,“-1”位于bash不进行数学运算的地方。通常,在${ }内,-something表示如果未定义变量,则应使用“ - ”之后的内容。在这里,它基本上被忽略了:

$ echo "${#array[@]-1}"    # wrong
5
$ echo "${#array[@]}"    # equivalent, still wrong
5

为了做数学,你需要进入算术环境。您可以使用$(( ))

执行此操作
$ echo "$(( ${#array[@]} - 1 ))"    # right
4

...但在这种情况下,使用算术测试表达式(( ))而不是使用[ ]的普通测试更简单。请注意,[ ](( ))之间的比较运算符不同,您不必使用$来获取变量的值;它出来是这样的:

while (( j < ${#array[@]} - 1 ))    # right

好吧,除了你没有在循环中增加j,所以它只是无休止地迭代。在循环中添加((j++)),或使用for循环。你在评论中有这种方法,但你也需要在那里进行相同的语法修正:

for ((j = 0; j < ${#array[@]} - 1; j++))    # also right

实际上,还有另一种方法可以做到这一点;你可以使用${!array[@]}来获取数组的索引列表(“!”使它给出索引,而不是内容):

for j in "${!array[@]}"    # still right

下一个问题:在for i in {$array}中,它只是获取数组的第一个元素,并在其周围放置一个“{}”:

$ echo "{$array}"    # wrong
{15}

这基本上与外部while / for循环做同样的事情,所以这些解决方案都适用于此。

接下来,y=${array[$i]+1} - 再次,这不是算术上下文,因此+无法完成您所期望的 。在${ }中,+something表示“如果定义了变量,则使用值'某事'”。由于array已定义,因此始终将y设置为“1”。要解决此问题,只需将+1放在[ ]内( 是算术上下文,因此数学运算正常)。此外,您可以在$上取消i,因为它是算术上下文,变量引用是自动的:

$ echo "${array[$i]+1}"    # wrong
1
$ echo "${array[i+1]}"    # right
93

接下来,为了进行比较if [ $x -gt $y ]if需要then(在下一行或由分号分隔的同一行:

if [ $x -gt $y ]; then    # right

if [ $x -gt $y ]
then    # also right
顺便说一下,你在结尾附近的评论中if ((array[i] > array[i+1]))可以很好地获取和比较数组元素。如果您使用then

好的,最后一个问题:在${array[$i]}=${array[$i+1]}中,你告诉bash获取数组的i元素中的值,并将该名称的变量设置为下一个值元件。嗯,有点,它实际上甚至比那更奇怪。无论如何,问题在于,当分配给数组元素时,不要将其包装在${ }中:

$ ${array[$i]}=${array[$i+1]}    # wrong
-bash: 30=93: command not found
$ array[$i]=${array[$i+1]}    # right
$ array[i]=${array[i+1]}    # also right

答案 1 :(得分:0)

for i in {$array}由数组元素循环,因此$i是一个字符串,而不是索引。要按索引循环:

for ((i=0; i<${#array[*]}; i++));
do
    x=${array[i]}
    y=${array[i+1]}
    if [ $x -gt $y ]
        temp=${array[i]}
        ${array[i]}=${array[i+1]}
        ${array[i+1]}=$temp
    fi
done

请注意,$前面不需要i符号。

此外,还有内置的排序方式;例如see the answers here