쉘 인수를 역순으로 인쇄 인수를 스크립트에 역순으로 인쇄하는

나는 약간 붙어있다. 내 임무는 세 번째와 네 번째를 제외하고 인수를 스크립트에 역순으로 인쇄하는 것입니다.

내가 가진 것은이 코드입니다.

#!/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 인사)을 싫어함에 따라 솔루션이없는 솔루션을 찾고 있지만 찾을 수 없습니다.

인수의 위치를 ​​동적으로 정의하려면 어떻게해야합니까?

추신 : 숙제가 아닙니다. 시험을 위해 쉘을 배우고 있으므로 오래된 시험을 풀려고합니다.



답변

eval동적으로 선택된 위치로 위치 매개 변수에 액세스 할 수있는 유일한 방법입니다. 사용하지 않는 값 대신 인덱스를 명시 적으로 반복하면 스크립트가 더 명확 해집니다. expr골동품 Bourne 쉘에서 스크립트를 실행 하지 않는 한 필요하지 않습니다 . $((…))산술은 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이름이 지정된 매개 변수 또는 숫자 (위치 매개 변수를 나타내는) 일 때 작동합니다 . 당신이 그것을하는 동안, 당신은 다른 배쉬 편의 기능을 사용할 수 있습니다.

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

답변

나는 이것을하는 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

전용 스크립트 대신 함수를 사용할 수도 있습니다.


답변

이것은 정확하고 위험하지 않은 eval의 사용입니다. 당신은 당신이하고있는 내용을 완벽하게 제어 eval합니다.

여전히 기분이 좋지 않으면 이식성에 신경 쓰지 않는다면 Bash의 ${!i}간접 구문을 사용할 수 있습니다 .


답변

위치 매개 변수에 개행 문자가 포함되지 않았다고 가정하십시오.

[ "$#" -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

답변

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>

답변

기본적으로 모든 쉘 :

printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null

그리고 서브 쉘을 사용할 필요 가 없습니다 . 예를 들면 다음과 같습니다.

set -x a b c
{ last= PS4=\${last:=\${$#}}; set +x; } 2>/dev/null
echo "$last"

…인쇄물…

c

그리고 여기 alias에 인수를 앞뒤로 인쇄 할 쉘 을 설정할 수있는 쉘 함수가 있습니다 :

tofro() case $1 in (*[!0-9]*|'') ! :;;(*) set "$1"
        until   [ "$1" -eq "$(($#-1))" ]    &&
                shift && alias args=":; printf \
            \"%.\$((\$??\${#*}:0))s%.\$((!\$??\${#*}:0))s\n\" $* "
        do      [ "$#" -gt 1 ] &&
                set "$@ \"\${$#}\" " '"${'"$((1+$1-$#))"'}"' ||
                set "$1" '"$1" "${'"$1"'}"'
        done;   esac

인수에 대한 리터럴 값을 저장하려고 시도하지 않고 다음과 같은 문자열을 args alias:

:;printf    "%.$(($??${#*}:0))s%.$((!$??${#*}:0))s\n" \
            "$1" "${3}" "${2}"  "${2}" "${3}"  "${1}"

… 따라서 앞뒤로 매개 변수에 대한 참조 만 저장합니다. 인수로 주어진 수만큼 카운트를 저장합니다. 그리고 위와 같이 alias생성되었습니다 :

tofro 3

printf의 동작은 이전 명령의 반환 값을 기반으로 영향을받습니다. 항상 :null 명령이므로 일반적으로 true입니다. printf인쇄 할 때마다 인수의 절반을 건너 뜁니다. 기본적으로 인수는 가장 작은 숫자에서 가장 큰 숫자로 인쇄됩니다. 그러나 당신이 방금 할 경우 :

! args

… 반대로 인쇄합니다.

별명은 리터럴 값을 저장하지 않으므로 실제 인수는 변경 될 수 있지만 정적 값은 그대로 유지되지만 여전히 많은 수를 참조합니다. 예를 들면 다음과 같습니다.

set one two three
tofro 3
args; ! args
shift; args; ! args

… 인쇄 …

one
two
three
three
two
one
two
three


three
two

그러나 별칭 재설정은 다음과 같이 수행 할 수 있습니다.

tofro 2
args; ! args

… 그래서 인쇄합니다 …

two
three
three
two

답변

declare -a argv=( "$@" )
for (( i=$((${#argv[@]}-1)) ; i>=0 ; i=$(($i-1)) )) ; do
        echo "${argv[$i]}"
        # use "${argv[$i]}" in here...
done