以相反的顺序打印 shell 参数

以相反的顺序打印 shell 参数

我有点卡住了。我的任务是以相反的顺序打印脚本的参数,除了第三个和第四个。

我所拥有的是这段代码:

#!/bin/bash

i=$#
for arg in "$@"
do
    case $i
    in
        3) ;;
        4) ;;
        *) eval echo "$i. Parameter: \$$i";;
    esac
    i=`expr $i - 1`
done

由于我讨厌 eval (向 PHP 致敬),我正在寻找一种没有它的解决方案,但我找不到。

如何动态定义参数的位置?

PS:不,这不是作业,我正在为考试学习 shell,所以我尝试解决旧的考试。

答案1

eval是通过动态选择的位置来访问位置参数的唯一可移植方式。如果您显式循环索引而不是值(您没有使用),您的脚本会更清晰。请注意expr,除非您希望脚本在古董 Bourne shell 中运行,否则您不需要;$((…))算术是 POSIX 中的。将使用限制eval在尽可能小的片段;例如,不要使用eval echo,将值分配给临时变量。

i=$#
while [ "$i" -gt 0 ]; do
  if [ "$i" -ne 3 ] && [ "$i" -ne 2 ]; then
    eval "value=\${$i}"
    echo "Parameter $i is $value"
  fi
  i=$((i-1))
done

在 bash 中,您可以使用${!i}来表示名称为 的参数的值$i。当$i是命名参数或数字(表示位置参数)时,此方法有效。当您使用它时,您可以利用其他 bash 便利功能。

for ((i=$#; i>0; i--)); do
  if ((i != 3 && i != 4)); then
    echo "Parameter $i is ${!i}"
  fi
done

答案2

reverse我在我的路径上保留了一个脚本来执行此操作:

#!/bin/sh

if [ "$#" -gt 0 ]; then
    arg=$1
    shift
    reverse "$@"
    printf '%s\n' "$arg"
fi

用法示例:

$ reverse a b c '*' '-n'
-n
*
c
b
a

您还可以使用函数代替专用脚本。

答案3

假设位置参数不包含换行符:

[ "$#" -gt 0 ] && printf '%s\n' "$@" | #print in order
sed '3,4 d' |                          #skip 3 and 4
tac                                    #reverse (try tail -r on
                                       #non-GNU systems).

测试:

set 1 2 3 4 5 6
printf '%s\n' "$@" | 
sed '3,4 d' |
tac

测试输出:

6
5
2
1

答案4

zsh

$ set a 'foo bar' c '' '*'
$ printf '<%s>\n' "${(Oa)@}"
<*>
<>
<c>
<foo bar>
<a>

Oa是一个参数扩展标志,用于在扩展时对数组元素进行排序撤销数组索引。

排除 3 和 4:

$ printf '<%s>\n' "${(Oa)@[5,-1]}" "${(Oa)@[1,2]}"
<*>
<foo bar>
<a>

相关内容