쉘 스크립트에서 Shift를 사용하는 목적은 무엇입니까?

쉘 스크립트에서 Shift를 사용하는 목적은 무엇입니까?

나는 다음 스크립트를 발견했습니다.

#! /bin/bash                                                                                                                                                                                           

if (( $# < 3 )); then
  echo "$0 old_string new_string file [file...]"
  exit 0
else
  ostr="$1"; shift
  nstr="$1"; shift  
fi

echo "Replacing \"$ostr\" with \"$nstr\""
for file in $@; do
  if [ -f $file ]; then
    echo "Working with: $file"
    eval "sed 's/"$ostr"/"$nstr"/g' $file" > $file.tmp 
    mv $file.tmp $file
  fi  
done

그들이 사용하는 선의 의미는 무엇입니까 shift? 스크립트는 최소한 매개변수와 함께 사용해야 한다고 생각하는데...?

답변1

shiftbash매개변수 목록의 시작 부분에서 매개변수를 제거하는 내장 함수 입니다 . 스크립트에 제공된 3개의 인수를 $1, 에서 $2사용할 수 있다고 가정하면 $3호출은 new 를 shift 생성합니다 . A는 2만큼 새로운 old 로 변환됩니다 . 자세한 내용은 여기를 참조하세요.$2$1shift 2$1$3

답변2

Goldilocks의 의견과 휴먼 레퍼런스에 설명된 대로 shift위치 매개변수( 등)를 다시 할당하여 $1$2의 이전 값을 $1가져옵니다 . *   이전 값은 폐기됩니다. (변경되지 않음.) 이를 수행하는 몇 가지 이유는 다음과 같습니다.$2$2$3$1$0

  • 10번째 매개변수(있는 경우)에 더 쉽게 액세스할 수 있습니다.  작동하지 않습니다. a와 연결된 $10것으로 해석됩니다 (그래서 비슷한 결과가 생성될 수 있음 ). a 다음의 10번째 매개변수는 가 됩니다 . (그러나 대부분의 최신 쉘에서는 를 사용할 수 있습니다 .)$10Hello0shift$9${10}
  • ~처럼Bash 초보자 가이드매개변수를 반복하는 데 사용할 수 있음이 입증되었습니다. IMNSHO, 이것은 투박합니다 for.
  • 예제 스크립트와 마찬가지로 몇 가지 매개변수를 제외한 모든 매개변수를 동일한 방식으로 쉽게 처리할 수 있습니다. 예를 들어, 스크립트에서 $1$2는 텍스트 문자열이고, $3기타 모든 매개변수는 파일 이름입니다.

결과는 다음과 같습니다. 스크립트가 호출 Patryk_script되고 호출된다고 가정합니다.

Patryk_script USSR Russia Treaty1 Atlas2 Pravda3

스크립트는 본다

$1 = USSR
$2 = Russia
$3 = Treaty1
$4 = Atlas2
$5 = Pravda3

이 명령문은 ostr="$1"변수를 ostr로 설정합니다 USSR. 첫 번째 shift문은 위치 매개변수를 다음과 같이 변경합니다.

$1 = Russia
$2 = Treaty1
$3 = Atlas2
$4 = Pravda3

이 명령문은 nstr="$1"변수를 nstr로 설정합니다 Russia. 두 번째 shift문은 위치 매개변수를 다음과 같이 변경합니다.

$1 = Treaty1
$2 = Atlas2
$3 = Pravda3

그런 다음 루프는 파일의 ( )를 for( )로 변경합니다.USSR$ostrRussia$nstrTreaty1Atlas2Pravda3



스크립트에 몇 가지 문제가 있습니다.

  1. $@의 파일에 대해서는 다음을 수행하십시오.

    스크립트가 다음과 같이 호출되는 경우

    Patryk_script 소련 러시아 조약 1 "World Atlas 2" Pravda 3

    그것은 본다

    1 USD = 소련
    2달러 = 러시아
    $3 = 조약 1
    $4 = 월드 아틀라스 2
    $5 = 프라우다 3

    그러나 $@공백은 World Atlas2인용되지 않았기 때문에 인용되지 않으며 for루프는 Treaty1, World, Atlas2및 4개의 파일이 있다고 생각합니다 Pravda3. 이것은 아마도

    "$@"에 있는 파일의 경우 다음을 수행하십시오.

    (인수에 특수 문자를 인용하십시오) 또는 간단히

    파일의 경우

    (더 긴 버전과 동일)

  2. eval "sed 's/"$ostr"/"$nstr"/g' $file"

    이를 로 설정할 필요가 없으며 eval확인되지 않은 사용자 입력을 에 전달하는 것은 eval위험할 수 있습니다. 예를 들어 스크립트가 다음과 같이 호출되는 경우

    Patryk_script "'; rm *;'" 러시아 조약 1 Atlas2 Pravda3

    그것은 수행됩니다 rm *! 예를 들어 sudo웹 인터페이스를 통해 스크립트를 실행하거나 호출할 수 있는 경우 스크립트를 호출하는 사용자보다 더 높은 권한으로 실행할 수 있는 경우 이는 큰 문제입니다 . 디렉토리에서 직접 사용하는 경우에는 그다지 중요하지 않을 수 있습니다. 하지만 다음과 같이 변경될 수 있습니다.

    sed "s/$ostr/$nstr/g" "$file"

    여전히 약간의 위험은 있지만 훨씬 덜 위험합니다.

  3. if [ -f $file ], > $file.tmp및 는 공백(또는 기타 흥미로운 문자)이 포함될 수 있는 파일 이름을 처리하기 위해 각각 , 및 mv $file.tmp $file 이어야 합니다 . (이 명령은 공백이 포함된 파일 이름도 삭제합니다.)if [ -f "$file" ]> "$file.tmp"mv "$file.tmp" "$file"eval "sed …


* shift 선택적 인수를 취합니다: 이동할 인수 수를 지정하는 양의 정수. 기본값은 1( 1)입니다. 예를 들어 , 가 되는 원인 shift 4등 이 있습니다. (예제에서 참고하세요.$5$1$6$2Bash 초보자 가이드그건 잘못 됐어. ) 스크립트를 다음과 같이 수정할 수 있습니다.

ostr="$1"
nstr="$2"
shift 2

이것이 더 명확하다고 볼 수 있습니다.



미주/ 경고하다:

Windows 명령 프롬프트(배치 파일) 언어는 SHIFT기본적으로 Unix 셸의 명령과 동일한 작업을 수행하는 명령 도 지원 shift하지만 사람들이 혼동하지 않도록 숨길 중요한 차이점이 하나 있습니다.

  • 이와 같은 명령 SHIFT 4은 오류이며 "SHIFT 명령에 대한 잘못된 인수" 오류 메시지가 생성됩니다.
  • SHIFT /n, 어디n0에서 8 사이의 정수이며 유효하지만 이동되지는 않습니다.n 이류. 한번 변신하고,에서 시작하다이것N 번째 매개변수입니다. 따라서 SHIFT /4 결과 %5(5번째 매개변수)는 가 되고 %4,  %6, %5이런 식으로 매개변수 0~3만 남습니다.

답변3

가장 간단한 설명은 이것이다. 다음 명령을 고려하십시오.

/bin/command.sh SET location Cebu
/bin/command.sh SET location Cebu, Philippines 6014 

도움이 없으면 shift값이 임의로 길어질 수 있으므로 위치의 전체 값을 추출할 수 없습니다. 두 번 이동하면 다음과 같이 args SET및가 location제거됩니다.

x="$@"
echo "location = $x"

$@그 물건을 오랫동안 쳐다보세요 . 이는 x공백과 쉼표가 포함되어 있더라도 전체 위치를 변수에 저장할 수 있음을 의미합니다 . 즉, shift변수 에 남아 있는 값을 호출한 다음 검색합니다 $@.

고쳐 쓰다 아래에 개념과 사용법을 보여주는 매우 짧은 코드 조각을 추가했습니다. shift이것이 없으면 필드를 올바르게 추출하는 것이 매우 어려울 것입니다.

#!/bin/sh
#

[ $# -eq 0 ] && return 0

a=$1
shift
b=$@
echo $a
[ -n "$b" ] && echo $b

설명하다: 이후 shift, 가변두번째공백 등에 관계없이 전달된 나머지 콘텐츠를 포함해야 합니다. 이것은 [ -n "$b" ] && echo $b보호 장치입니다. 우리는 인쇄만 합니다.두번째내용이 있는 경우입니다.

답변4

shift명령줄 인수를 호출할 때마다 요소가 표시되는 FIFO 대기열로 처리합니다.

array = [a, b, c]
shift equivalent to
array.popleft
[b, c]
$1, $2,$3 can be interpreted as index of the array.
$# is the length of array

관련 정보