쉘 스크립트에서 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? 스크립트가 적어도 인수와 함께 사용해야한다고 가정합니다 …?



답변

shiftbash인수 목록의 시작 부분에서 인수를 제거 하는 내장 기능입니다. 스크립트로 제공되는 3 개 인자에서 사용할 수있는 점을 감안 $1, $2, $3, 호출은하는 shift$2새를 $1. A shift 2는 두 가지를 새로운 $1것으로 만들어 옮길 것이다 $3. 자세한 내용은 여기를 참조하십시오.


답변

골디락스 ‘주석 인류의 참조는 설명 된 바와 같이,
shift(위치 매개 변수를 재 할당하고 $1, $2그 정도로 등) $1의 이전 값을 얻어 $2,
$2의 값을 취 $3*  
의 값을 구 $1폐기된다. ( $0변경되지 않음)이를 수행하는 몇 가지 이유는 다음과 같습니다.

  • 10 번째 인수 (있는 경우)에 더 쉽게 액세스 할 수 있습니다. 
    $10작동하지 않습니다 –로 $1연결된 것으로 해석되어 0
    (와 같이 생성 될 수 있습니다 Hello0). a shift다음에 열 번째 인수가됩니다 $9. (그러나 대부분의 현대 쉘에서는을 사용할 수 있습니다 ${10}.)
  • 초보자를위한 배쉬 가이드 (Bash Guide for Beginners)가 설명 하듯이 , 인수를 반복하는 데 사용될 수 있습니다. 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( $ostr에) Russia( $nstr파일에서) Treaty1, Atlas2그리고 Pravda3.



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

  1. $ @ 파일; 하다

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

    Patryk_script 소련 러시아 조약 1 "세계지도 책 2"Pravda3

    그것은 본다

    $ 1 = 소련
    $ 2 = 러시아
    $ 3 = 조약 1
    $ 4 = 세계 아틀라스 2
    5 달러 = Pravda3

    있기 때문에, $@인용되지 않고있는 공간을 World Atlas2인용하고 있지 않습니다 for루프는 네 개의 파일이있다 생각한다 : Treaty1, World, Atlas2,와 Pravda3. 이것은 둘 중 하나 여야합니다

    "$ @"파일; 하다

    (인수에서 특수 문자를 인용) 또는 단순히

    파일을 위해

    (더 긴 버전과 동일).

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

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

    Patryk_script " '; rm *;'"Russia Treaty1 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$2등등합니다. ( 초보자를위한 Bash Guide 의 예제 가 잘못되었습니다.) 따라서 스크립트는 다음과 같이 수정 될 수 있습니다.

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

더 명확한 것으로 간주 될 수 있습니다.



끝 참고 / 경고 :

Windows 명령 프롬프트 (일괄 파일) 언어 SHIFT는 기본적으로 shiftUnix 쉘 의 명령 과 동일한 기능을 수행 하는 명령을 지원 합니다.

  • SHIFT 4“SHIFT 명령에 잘못된 매개 변수”오류 메시지가 표시되는 오류 와 같은 명령입니다.
  • SHIFT /n, 여기서 n0에서 8 사이의 정수는 유효하지만 시간 은 이동하지 않습니다 . 그것은 한 번 이동 로 시작 N  인수 일. 그래서 원인 (다섯 번째 인수)가되는 이 될 만 3를 통해 인수 0을 떠나, 등등합니다.n SHIFT /4%5%4, 
    %6%5

답변

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

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

도움 없이는 shift이 값이 임의로 길어질 수 있으므로 위치의 전체 값을 추출 할 수 없습니다. 두 번 교대하면 인수가 다음 SETlocation같이 제거됩니다.

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

$@일을 아주 오래 쳐다 봐 즉, x공백과 쉼표가 있어도 완전한 위치를 변수에 저장할 수 있습니다 . 요약하면, 우리는 호출 shift하고 나중에 변수에서 남은 값을 검색합니다 $@.

업데이트
나는 개념과 유용성을 보여주는 매우 짧은 스 니펫 아래에 shift필드를 올바르게 추출하는 것이 매우 어려울 것입니다.

#!/bin/sh
#

[ $# -eq 0 ] && return 0

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

설명 : 뒤에 shift변수 b 는 공백 등의 문제없이 전달되는 나머지 내용을 포함해야합니다 . 내용이있는 경우 [ -n "$b" ] && echo $b에만 b를 인쇄하도록 보호 합니다.


답변

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


답변