Як коментар Золотоволоска і посилання людства описують,
shiftперепризначення позиційних параметрів ( $1, $2і т.д.) , так що $1бере на старе значення $2,
$2приймає значення $3, і т.д. *
Старе значення $1відкидається. ( $0не змінюється.) Деякі причини цього включають:
- Це дозволяє вам легше отримати доступ до десятого аргументу (якщо такий є).
$10не працює - інтерпретується як $1об'єднаний з 0
(і може призвести до подібного Hello0). Після a shiftстає десятим аргументом $9. (Однак у більшості сучасних оболонок можна використовувати ${10}.)
- Як демонструє керівництво Bash для початківців , його можна використовувати для перегляду аргументів. ІМНШО, це незграбно;
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" Правда3
це бачить
$ 1 = СРСР
$ 2 = Росія
$ 3 = Договір1
$ 4 = Всесвітній атлас2
$ 5 = Правда3
але, тому що $@не котируються, простір в World Atlas2не котируються, і forцикл думає , що має чотири файли: Treaty1, World, Atlas2і Pravda3. Це має бути будь-яке
для файлу у "$ @"; робити
(цитувати будь-які спеціальні символи в аргументах) або просто
для файлу
(що еквівалентно більш тривалої версії).
eval "sed 's /" $ ostr "/" $ nstr "/ g' $ файл"
Не потрібно, щоб це було eval, і передача неперевіреного вводу користувача на базу evalможе бути небезпечною. Наприклад, якщо сценарій викликається як
Patryk_script "'; rm *;'" Російський договір1 Атлас2 Правда3
це виконає rm *! Це викликає велике занепокоєння, якщо сценарій можна запускати з привілеями, вищими, ніж користувачі, які його викликають; наприклад, якщо це можна запустити через sudoвеб-інтерфейс або викликати ним. Це, мабуть, не так важливо, якщо ви просто використовуєте його як у своєму каталозі. Але це можна змінити на
sed "s / $ ostr / $ nstr / g" "$ файл"
Це все ще має певні ризики, але вони набагато менш серйозні.
if [ -f $file ], > $file.tmpІ mv $file.tmp $file
має бути if [ -f "$file" ], > "$file.tmp"і mv "$file.tmp" "$file", відповідно, для обробки імен файлів , які можуть мати прогалини (або інші забавні символи) в них. ( eval "sed …Команда також манглює імена файлів, у яких є пробіли.)
* shift приймає необов’язковий аргумент: додатне ціле число, яке вказує, скільки параметрів потрібно змістити. За замовчуванням - один ( 1). Наприклад, shift 4причини $5
ставати $1,
$6ставати $2тощо. (Зверніть увагу, що приклад у Посібнику з Bash для початківців невірний.) І тому ваш сценарій можна змінити
ostr="$1"
nstr="$2"
shift 2
що може вважатися більш зрозумілим.
Закінчення Примітка / Попередження:
Мова командного рядка Windows (пакетний файл) також підтримує SHIFTкоманду, яка в основному робить те ж саме, що і shiftкоманда в оболонках Unix, з однією разючою різницею, яку я приховую, щоб спробувати не допустити, щоб люди не плутали її:
- Така команда
SHIFT 4- це помилка, яка дає повідомлення про помилку "Недійсний параметр для команди SHIFT".
SHIFT /n, де nціле число між 0 і 8, є дійсним - але воно не змінює час . Це зрушує один раз, починаючи з з п - го аргументу. Тому змушує (п’ятий аргумент) стати , і так далі, залишаючи аргументи від 0 до 3.n SHIFT /4%5%4,
%6%5
pushdіpopd).