Bash เกิดข้อผิดพลาดบรรทัดที่ 8: $ 1: ตัวแปรที่ไม่ถูกผูก


15

ฉันพยายามที่จะเรียนรู้วิธีใช้ getopts เพื่อที่ฉันจะได้สคริปต์ที่มีการวิเคราะห์คำ (แม้ว่าฉันคิดว่า getopts น่าจะดีกว่า) ฉันพยายามเขียนสคริปต์ง่าย ๆ เพื่อคืนค่าเปอร์เซ็นต์การใช้งานพาร์ติชัน ปัญหาคือว่าหนึ่งในฟังก์ชั่นทุบตีของฉันดูเหมือนจะไม่ชอบที่ฉันอ้างอิง$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 ไม่ฉันเดาไม่ได้ แต่ฉันไม่แน่ใจว่าฉันสามารถเปลี่ยนชื่อตอนนี้
Timothy Pulliam

ควรมีข้อความ "แก้ไข" ขนาดเล็กใต้โพสต์ใต้แท็กในคำถาม
ilkkachu

คำตอบ:


29

set -uจะยกเลิกตรงตามที่คุณอธิบายหากคุณอ้างอิงตัวแปรที่ยังไม่ได้ตั้งค่า คุณกำลังเรียกใช้สคริปต์ของคุณโดยไม่มีข้อโต้แย้งใด ๆ ดังนั้นget_percentจะถูกเรียกใช้โดยไม่มีอาร์กิวเมนต์ทำให้$1ไม่สามารถตั้งค่าได้

ตรวจสอบสิ่งนี้ก่อนที่จะเรียกใช้ฟังก์ชันของคุณหรือใช้การขยายเริ่มต้น ( ${1-default}จะขยายเป็นdefaultหากยังไม่ได้ตั้งค่าเป็นอย่างอื่น)


ฉันสงสัยสิ่งนี้ แต่ฉันไม่สามารถคิดวิธีรอบ ดูเหมือนว่าการขยายเริ่มต้นจะได้รับการแก้ไขแล้ว ขอบคุณมาก!
ทิโมธี Pulliam

7
โดยเฉพาะอย่างยิ่งหนึ่งสามารถใช้[ -n "${1-}" ](นั่นคือด้วยค่าเริ่มต้นที่ว่างเปล่า) เพื่อดูว่าพารามิเตอร์มีการตั้งค่าและไม่ว่างเปล่า; หรือ[ "${1+x}" = x ]ดูว่ามีการตั้งค่าไว้หรือไม่แม้ว่าจะว่างเปล่าก็ตาม
ilkkachu

ฉันยังคงได้รับข้อผิดพลาดตัวแปรที่ไม่ได้คาดไว้แม้จะใช้if [[ -n ${1-default} ]]
Chaitanya Bapat

@ChaitanyaBapat ผมก็ยังคงได้รับunbound variableเป็นอย่างดีจนผมใช้แทน:- -อย่างน้อยที่สุดฉันก็${1:-default}ไม่มีความผิดเลย
Adam Badura

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$#


คุณสามารถอธิบายเพิ่มเติมเกี่ยวกับวิธีใช้ $ # และวิธีตรวจสอบได้อย่างไร ขอบคุณ
Chaitanya Bapat

1
ฉันเพิ่มตัวอย่าง
RalfFriedl

3

เนื่องจากbashคุณสามารถเลี่ยงขั้นตอนการตรวจสอบ$1การตั้งค่าและใช้เพียงแค่"$@"( $1เป็นพารามิเตอร์แรก$@คือทั้งหมดของพวกเขาเมื่อดับเบิลอ้างถึงมันจะหายไปอย่างสมบูรณ์หากไม่มีค่าซึ่งหลีกเลี่ยงการถูกจับset -u):

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

ฉันยัง tweaked ส่วนที่เหลือของบรรทัดเล็กน้อยเพื่อให้คุณไม่ได้รับ {space} {tab} {space} ระหว่างสองค่าที่คุณออก แต่ insead คุณได้รับเพียง {tab} ถ้าคุณต้องการให้สองช่องว่างที่มองไม่เห็นจริงๆแล้วเปลี่ยนไปใช้งานที่awkprintf "%s \t %s\n", $1, $5


ฉันจะต้องตรวจสอบเรื่องนี้ ฉันไม่คุ้นเคยกับประเภทของตัวแปรนั้น ขอบคุณ
ทิโมธี Pulliam

@TimothyPulliam ฉันได้เพิ่มคำอธิบายสั้น ๆ$@สำหรับคุณ
roaima
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.