나는 다음 스크립트를 발견했습니다.
#! /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
shift
bash
매개변수 목록의 시작 부분에서 매개변수를 제거하는 내장 함수 입니다 . 스크립트에 제공된 3개의 인수를 $1
, 에서 $2
사용할 수 있다고 가정하면 $3
호출은 new 를 shift
생성합니다 . A는 2만큼 새로운 old 로 변환됩니다 . 자세한 내용은 여기를 참조하세요.$2
$1
shift 2
$1
$3
답변2
Goldilocks의 의견과 휴먼 레퍼런스에 설명된 대로
shift
위치 매개변수( 등)를 다시 할당하여 $1
등 $2
의 이전 값을 $1
가져옵니다 . * 이전 값은 폐기됩니다. (변경되지 않음.) 이를 수행하는 몇 가지 이유는 다음과 같습니다.$2
$2
$3
$1
$0
- 10번째 매개변수(있는 경우)에 더 쉽게 액세스할 수 있습니다. 작동하지 않습니다. a와 연결된
$10
것으로 해석됩니다 (그래서 비슷한 결과가 생성될 수 있음 ). a 다음의 10번째 매개변수는 가 됩니다 . (그러나 대부분의 최신 쉘에서는 를 사용할 수 있습니다 .)$1
0
Hello0
shift
$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
$ostr
Russia
$nstr
Treaty1
Atlas2
Pravda3
스크립트에 몇 가지 문제가 있습니다.
$@의 파일에 대해서는 다음을 수행하십시오.
스크립트가 다음과 같이 호출되는 경우
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
. 이것은 아마도"$@"에 있는 파일의 경우 다음을 수행하십시오.
(인수에 특수 문자를 인용하십시오) 또는 간단히
파일의 경우
(더 긴 버전과 동일)
eval "sed 's/"$ostr"/"$nstr"/g' $file"
이를 로 설정할 필요가 없으며
eval
확인되지 않은 사용자 입력을 에 전달하는 것은eval
위험할 수 있습니다. 예를 들어 스크립트가 다음과 같이 호출되는 경우Patryk_script "'; rm *;'" 러시아 조약 1 Atlas2 Pravda3
그것은 수행됩니다
rm *
! 예를 들어sudo
웹 인터페이스를 통해 스크립트를 실행하거나 호출할 수 있는 경우 스크립트를 호출하는 사용자보다 더 높은 권한으로 실행할 수 있는 경우 이는 큰 문제입니다 . 디렉토리에서 직접 사용하는 경우에는 그다지 중요하지 않을 수 있습니다. 하지만 다음과 같이 변경될 수 있습니다.sed "s/$ostr/$nstr/g" "$file"
여전히 약간의 위험은 있지만 훨씬 덜 위험합니다.
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 초보자 가이드그건 잘못 됐어. ) 스크립트를 다음과 같이 수정할 수 있습니다.
ostr="$1"
nstr="$2"
shift 2
이것이 더 명확하다고 볼 수 있습니다.
미주/ 경고하다:
Windows 명령 프롬프트(배치 파일) 언어는 SHIFT
기본적으로 Unix 셸의 명령과 동일한 작업을 수행하는 명령 도 지원 shift
하지만 사람들이 혼동하지 않도록 숨길 중요한 차이점이 하나 있습니다.
- 이와 같은 명령
SHIFT 4
은 오류이며 "SHIFT 명령에 대한 잘못된 인수" 오류 메시지가 생성됩니다.SHIFT /n
, 어디n
0에서 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