识别是否存在并从 shell args 中删除特定参数

识别是否存在并从 shell args 中删除特定参数

我必须检查脚本的 shell 参数中是否存在特定参数“java8”,如果存在则将其删除。我还希望将其存储在其他变量中,但希望将其从我的 $* 中删除。

我尝试使用 getopts 检查 arg 是否存在,但我不知道如何删除 argument 。

请注意 - 检查“java8”的 arg 位置未知,我可以在任何地方

while getopts "f:" flag
do
     case $flag in
         f)
           echo $OPTARG
           ;;
     esac
done
echo $*
~

所以基本上当我调用时 -

./test.sh arg1 arg2 -f java8 arg3

执行 getopts 块后,剩余的参数将是

参数1、参数2、参数3

答案1

对于任何 POSIX shell(不使用临时数组):从位置参数列表中删除-f后跟java8或 的任何实例,同时计算此类删除选项的数量 - 参数包含在变量 中。-fjava8found

skip=0 found=0
for arg do
    case $1 in
        -f)
            if [ "$2" = java8 ]; then
                skip=2
                found=$(( found + 1 ))
            fi
            ;;
        -f*)
            if [ "$1" = -fjava8 ]; then
                skip=1
                found=$(( found + 1 ))
            fi
    esac

    if [ "$skip" -eq 0 ]; then
        set -- "$@" "$1"
    else
        skip=$(( skip - 1 ))
    fi
    shift
done

if [ "$skip" -eq 1 ]; then
    set -- "$@" -f
    found=$(( found - 1 ))
fi

printf 'Args: %s\n' "$*"
printf 'Found = %d\n' "$found"

上述循环的迭代次数与位置参数的初始数量一样多。

如果第一个位置参数为-f,则测试第二个位置参数是否为java8。如果测试是真的,那么我们需要跳过这两个参数,因此计数器skip设置为 2。我们还递增found以表明我们又找到了 的一个实例-f java8

如果第一个位置参数是-fjava8,那么我们需要跳过这个单个参数,因此计数器skip设置为 1。我们还递增found以指示我们又找到了 的一个实例-fjava8(与find 相同-f java8)。

在该语句之后,除了递减计数器并关闭第一个位置参数(如果非零)case之外,我们不执行任何操作。如果为零,我们在调用之前将第一个位置参数移动到列表的末尾,从而有效地允许我们保留的参数在列表中循环返回,同时删除不需要的参数。skipshiftskipskipshift

由于我们以循环方式使用位置参数列表,因此如果最后一个参数是-f且第一个参数是 ,我们将丢失最后一个参数java8。这就是最后一条if语句所要防止的。

答案2

也许是这样的?我假设您想删除-f java8...

#!/bin/bash

while (( $# )); do
    if [[ $1 = "-f" ]] && [[ $2 = "java8" ]]; then
        shift 2
        continue
    fi

    args+=( "$1" )
    shift
done

echo "${args[*]}"

用法示例:

$ ./argtest.sh one two three
one two three
$ ./argtest.sh one two -f java8 three four
one two three four
$ ./argtest.sh -f java8 -f foo -f bar
-f foo -f bar

相关内容