이 스크립트를 보았습니다.
#! /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). 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는 기본적으로 shiftUnix 쉘 의 명령 과 동일한 기능을 수행 하는 명령을 지원 합니다.
SHIFT 4“SHIFT 명령에 잘못된 매개 변수”오류 메시지가 표시되는 오류 와 같은 명령입니다.SHIFT /n, 여기서n0에서 8 사이의 정수는 유효하지만 시간 은 이동하지 않습니다 . 그것은 한 번 이동 로 시작 N 인수 일. 그래서 원인 (다섯 번째 인수)가되는 이 될 만 3를 통해 인수 0을 떠나, 등등합니다.nSHIFT /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