Bash кидає помилку, рядок 8: $ 1: незв'язана змінна


15

Я намагаюся навчитися використовувати getopts, щоб я міг мати сценарії з проаналізованим входом (хоча я думаю, що getopts може бути кращим). Я намагаюся просто написати простий скрипт, щоб повернути відсотки використання розділів. Проблема полягає в тому, що одна з моїх функцій bash не схожа на те, що я посилаюсь $1як на змінну в межах функції. Причина, на яку я посилаюсь, $1полягає в тому, що get_percentфункція може передаватися точкою монтажу як необов'язковий аргумент для відображення замість усіх точок монтування.

Сценарій

#!/usr/bin/bash

set -e
set -u
set -o pipefail

get_percent(){
    if [ -n "$1" ] 
    then
        df -h $1 | tail -n +2 | awk '{ print $1,"\t",$5 }'
    else
        df -h | tail -n +2 | awk '{ print $1,"\t",$5 }'
    fi
}

usage(){
    echo "script usage: $(basename $0) [-h] [-p] [-m mount_point]" >&2
}

# If the user doesn't supply any arguments, we run the script as normal
if [ $# -eq 0 ];
then
    get_percent
    exit 0
fi
# ...

Вихід

$ bash thing.sh
thing.sh: line 8: $1: unbound variable

$ bash -x thing.sh
+ set -e
+ set -u
+ set -o pipefail
+ '[' 0 -eq 0 ']'
+ get_percent
thing.sh: line 8: $1: unbound variable

Я не думаю, що це має щось спільне getopts, чи не так? Ваш сценарій виходить через, -uперш ніж дзвонити getopts.
ilkkachu

@ikkachu ні, я думаю, це не так. Але я не впевнений, що зараз можу змінити назву.
Тимофі Пуліам

Має бути невеличкий текст «редагувати» під публікацією, прямо під тегами у питанні
ilkkachu

Відповіді:


29

set -uбуде скасовувати саме так, як ви описуєте, якщо ви посилаєтесь на змінну, яка не була встановлена. Ви get_percentвикликаєте свій скрипт без аргументів, тому його викликають без аргументів, що призводить $1до відключення.

Або перевірте це перед тим, як викликати вашу функцію, або використовуйте розширення за замовчуванням ( ${1-default}буде розгорнуто до, defaultякщо вже не встановлено щось інше).


Я підозрював це, але не міг придумати способу цього. Розширення за замовчуванням, схоже, це виправило. Велике спасибі!
Тимофі Пуліам

7
Зокрема, можна було б використовувати [ -n "${1-}" ](тобто з порожнім значенням за замовчуванням), щоб побачити, чи встановлений параметр і не порожній; або [ "${1+x}" = x ]побачити, чи встановлено його, навіть якщо воно порожнє.
ilkkachu

Я все ще отримую незв'язану змінну помилку, незважаючи на використанняif [[ -n ${1-default} ]]
Чайтанья

@ChaitanyaBapat я все одно вийшов unbound variableтак само добре, поки не використовував :-замість цього -. Отже, для мене, принаймні, ${1:-default}жоден одиночок не підняв помилку.
Адам Бадура

6

Це ефект від set -u.

Ви можете перевірити $#функцію і уникати посилань, $1якщо вона не встановлена.

За допомогою $#ви можете отримати доступ до кількості параметрів. У глобальному контексті це кількість параметрів сценарію, у функції - це кількість параметрів функції.

У контексті питання це так

if [ $# -ge 1 ] && [ -n "$1" ]
then
    df -h $1 | tail -n +2 | awk '{ print $1,"\t",$5 }'
else
    df -h | tail -n +2 | awk '{ print $1,"\t",$5 }'
fi

Зверніть увагу, що ви повинні використовувати, [ $# -ge 1 ] && [ -n "$1" ]а не [ $# -ge 1 -a -n "$1" ], тому що це спочатку оцінить, $1а потім перевірить $#.


Чи можете ви пояснити, як використовувати $ # та як це перевірити? Спасибі
Чайтанья

1
Я додав приклад.
РальфФрідль

3

Оскільки це можна, bashви можете $1увімкнути перевірку на встановлення та просто використовувати "$@"( $1це перший параметр, $@чи всі вони; при подвійному цитуванні він повністю зникає, якщо у нього немає значень, що дозволяє уникнути його попадання set -u):

get_percent() {
    df -h "$@" | awk 'NR>1 { printf "%s\t%s\n", $1, $5 }'
}

Я також трохи змінив решту рядка, щоб у вас не було місця {space} {tab} {space} між двома виведеними значеннями, але в результаті цього ви отримаєте лише {tab}. Якщо ви дійсно хочете, щоб два невидимих ​​простору тоді змінили awkна використання printf "%s \t %s\n", $1, $5.


Мені доведеться розібратися в цьому. Я не знайомий з цим типом змінної. Спасибі
Тимофі Пуліам

@TimothyPulliam Я додав коротке пояснення $@для вас
roaima
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.