Bash ném lỗi, dòng 8: $ 1: biến không liên kết


13

Tôi đang cố gắng học cách sử dụng getopts để tôi có thể có các tập lệnh với đầu vào được phân tích cú pháp (mặc dù tôi nghĩ getopts có thể tốt hơn). Tôi đang cố gắng chỉ viết một tập lệnh đơn giản để trả về tỷ lệ phần trăm sử dụng phân vùng. Vấn đề là một trong các hàm bash của tôi dường như không thích mà tôi tham chiếu $1như một biến trong hàm. Lý do tôi tham chiếu $1là vì get_percentchức năng có thể được thông qua một điểm gắn kết như là một đối số tùy chọn để hiển thị thay vì tất cả các điểm gắn kết.

Kịch bản

#!/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
# ...

Đầu ra

$ 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

Tôi không nghĩ rằng điều này có liên quan getopts, phải không? Kịch bản của bạn thoát do -utrước khi gọi getopts.
ilkkachu

@ikkachu không tôi đoán là không. Nhưng tôi không chắc bây giờ tôi có thể thay đổi tiêu đề.
Timothy Pulliam

Cần có văn bản "chỉnh sửa" nhỏ dưới bài đăng, ngay bên dưới các thẻ trong một câu hỏi
ilkkachu

Câu trả lời:


29

set -usẽ hủy bỏ chính xác như bạn mô tả nếu bạn tham chiếu một biến chưa được đặt. Bạn đang gọi kịch bản của mình mà không có đối số, vì vậy get_percentđang được gọi mà không có đối số, gây ra $1không được đặt.

Kiểm tra cái này trước khi gọi hàm của bạn, hoặc sử dụng các mở rộng mặc định ( ${1-default}sẽ mở rộng thành defaultnếu chưa được đặt thành thứ khác).


Tôi nghi ngờ điều này, nhưng tôi không thể nghĩ ra cách nào khác. Mở rộng mặc định dường như đã sửa nó. Cảm ơn rât nhiều!
Timothy Pulliam

7
Cụ thể, người ta có thể sử dụng [ -n "${1-}" ](nghĩa là với giá trị mặc định trống) để xem tham số có được đặt và không trống; hoặc [ "${1+x}" = x ]để xem nếu nó được đặt, ngay cả khi trống.
ilkkachu

Tôi vẫn nhận được lỗi biến không liên kết mặc dù sử dụngif [[ -n ${1-default} ]]
Chaitanya Bapat

6

Đây là tác dụng của set -u.

Bạn có thể kiểm tra $#bên trong chức năng và tránh tham chiếu $1nếu nó không được đặt.

Với $#bạn có thể truy cập số lượng tham số. Trong bối cảnh toàn cầu, nó là số lượng tham số cho tập lệnh, trong một hàm, nó là số lượng tham số cho hàm.

Trong bối cảnh của câu hỏi, nó là

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

Lưu ý rằng bạn phải sử dụng [ $# -ge 1 ] && [ -n "$1" ]và không [ $# -ge 1 -a -n "$1" ], bởi vì trước tiên sẽ đánh giá $1và sau đó kiểm tra $#.


Bạn có thể giải thích thêm về cách sử dụng $ # và cách kiểm tra không? Cảm ơn
Chaitanya Bapat

1
Tôi đã thêm một ví dụ.
RalfFriedl

2

Vì đây là bashbạn có thể bỏ qua kiểm tra để $1được đặt và chỉ sử dụng "$@"( $1là tham số đầu tiên, $@là tất cả trong số chúng; khi được trích dẫn kép, nó sẽ biến mất hoàn toàn nếu không có giá trị, tránh bị bắt bởi set -u):

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

Tôi cũng đã điều chỉnh phần còn lại của dòng một chút để bạn không nhận được {dấu cách} {tab} {dấu cách} giữa hai giá trị bạn xuất ra nhưng cho rằng bạn chỉ nhận được một {tab}. Nếu bạn thực sự muốn hai không gian vô hình thì hãy thay đổi awkđể sử dụng printf "%s \t %s\n", $1, $5.


Tôi sẽ phải xem xét điều này. Tôi không quen thuộc với loại biến đó. Cảm ơn
Timothy Pulliam

@TimothyPulliam Tôi đã thêm một lời giải thích ngắn $@cho bạn
roaima
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.