이 스크립트를 보았습니다.
#! /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
? 스크립트가 적어도 인수와 함께 사용해야한다고 가정합니다 …?
답변
shift
bash
인수 목록의 시작 부분에서 인수를 제거 하는 내장 기능입니다. 스크립트로 제공되는 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
). ashift
다음에 열 번째 인수가됩니다$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
.
스크립트에는 몇 가지 문제가 있습니다.
-
$ @ 파일; 하다
스크립트가 다음과 같이 호출 된 경우
Patryk_script 소련 러시아 조약 1 "세계지도 책 2"Pravda3
그것은 본다
$ 1 = 소련 $ 2 = 러시아 $ 3 = 조약 1 $ 4 = 세계 아틀라스 2 5 달러 = Pravda3
있기 때문에,
$@
인용되지 않고있는 공간을World Atlas2
인용하고 있지 않습니다for
루프는 네 개의 파일이있다 생각한다 :Treaty1
,World
,Atlas2
,와Pravda3
. 이것은 둘 중 하나 여야합니다"$ @"파일; 하다
(인수에서 특수 문자를 인용) 또는 단순히
파일을 위해
(더 긴 버전과 동일).
-
eval "sed 's /"$ ostr "/"$ nstr "/ g'$ file"
이것이 될 필요는 없으며
eval
, 확인되지 않은 사용자 입력을에 전달하는eval
것은 위험 할 수 있습니다. 예를 들어, 스크립트가 다음과 같이 호출 된 경우Patryk_script " '; rm *;'"Russia Treaty1 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 Guide 의 예제 가 잘못되었습니다.) 따라서 스크립트는 다음과 같이 수정 될 수 있습니다.
ostr="$1"
nstr="$2"
shift 2
더 명확한 것으로 간주 될 수 있습니다.
끝 참고 / 경고 :
Windows 명령 프롬프트 (일괄 파일) 언어 SHIFT
는 기본적으로 shift
Unix 쉘 의 명령 과 동일한 기능을 수행 하는 명령을 지원 합니다.
SHIFT 4
“SHIFT 명령에 잘못된 매개 변수”오류 메시지가 표시되는 오류 와 같은 명령입니다.SHIFT /n
, 여기서n
0에서 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
이 값이 임의로 길어질 수 있으므로 위치의 전체 값을 추출 할 수 없습니다. 두 번 교대하면 인수가 다음 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
변수 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