for 循环中的范围变量可自定义

for 循环中的范围变量可自定义

我对 for 循环中的范围变量有疑问。在 for 循环中,我知道您可以使用 {..} 来定义范围。但我希望它是客户可定义的。所以脚本要求一个范围值,我希望它是灵活的。像这样:

#!/bin/bash
while true; 
    do
    echo "Some explenation..."
    read -p "Possible values are: ALL or RANGE (to define a specific range):" answer
    case $answer in
            #ALL
            [aA][lL][lL] )
            echo "ALL is selected, 1 to 250"
            RANGE="{1..250}"
            break
            ;;
            #RANGE
            [rR][aA][nN][gG][eE] )
            echo "Range is selected, please define a custom range. Notation should be like: <start>..<stop>"
            echo "or: <single> <single>"
            echo "or a combination of both. Like: 1..23 28 29 101..145 180 212"
            read RANGE
            break
            ;;
            #OTHERS
            * )
            echo "Typo error!! Not correct, type again ALL, PRI, SEC or 
RANGE"
            ;;
    esac
    done
echo ""
echo "Range for this execution is set to:"
echo "$RANGE"
for NEXI in $RANGE
    do
    sleep 0.2
    echo "Nexus number: $NEXI"
    done
echo ...

但是当我输入 {1..10} 52 54 {120..128} 时的输出是:

Nexus number: {1..10}
Nexus number: 52
Nexus number: 54
Nexus number: {120..128}

虽然我期望它是这样的:

Nexus number: 1
Nexus number: 2
Nexus number: 3
Nexus number: 4
Nexus number: 5
Nexus number: 6
Nexus number: 7
Nexus number: 8
Nexus number: 9
Nexus number: 10
Nexus number: 52
Nexus number: 54
Nexus number: 120
Nexus number: 121
... etc.

完全写出来了。

我可以改变什么来实现这个目标?

谢谢。

答案1

问题是大括号扩展发生在变量扩展之前。正如中所解释的man bash

展开的顺序是:大括号展开;波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和路径名扩展。

这意味着当您有类似$varwhich contains{1..3}和 do 的内容时echo "$var",shell 会查找可能的大括号扩展将变量扩展为其值。由于大括号位于变量中,这意味着此时 shell 看不到大括号,因此不会执行大括号扩展。

eval如果变量是一个范围,则一种解决方法是对其进行处理。在循环之前添加这些行for

if [[ $RANGE =~ ^[0-9]+\.\.[0-9]+$ ]]; then
        RANGE=$(eval echo {$RANGE})
fi

现在,更一般地说,避免在 shell 脚本中使用大写变量名通常是个好主意。环境变量通常是大写的,如果您碰巧使用与定义的环境变量相同的名称,则可能会导致混淆。因此,为了安全起见,请使用小写变量名。

另外,这是一个调试起来非常烦人的程序,使用起来也同样烦人。不要在运行时提示用户输入!相反,更改您的脚本并使其接受参数。输入值很困难、烦人、容易出错并且无法自动化。

答案2

将您的 shell 设置为ksh,此代码应该可以工作。

#!/usr/bin/ksh

相关内容