שאלה כיצד לקבוע אם משתנה bash ריק?


מהי הדרך הטובה ביותר לקבוע אם משתנה ב- bash ריק ("")?

שמעתי שמומלץ שאעשה זאת if [ "x$variable" = "x" ]

האם זה ה נכון דרך? (חייב להיות משהו פשוט יותר)


721
2018-05-12 17:54






תשובות:


פעולה זו תוחזר נכון אם משתנה אינו מוגדר או מוגדר למחרוזת הריקה ("").

if [ -z "$VAR" ];

986
2018-05-12 18:06



האם זה כולל אם משתנה IS מוגדר לערך של ""? - Brent
כן זה עושה ... "-z" בדיקות עבור מחרוזת באורך אפס. - David Z
if [ ! -z "$VAR" ]; - Aaron Copley
ההופכי של -z J -n  if [ -n "$VAR" ]; - Felipe Alvarez
הציטוטים הכפולים מבטיחים שהמשתנה לא יחולק. פשוט $var על שורת הפקודה יהיה לפצל על ידי רווח לבן שלה לתוך רשימה של פרמטרים, בעוד "$var" תמיד יהיה רק ​​פרמטר אחד. ציטוט משתנים לעתים קרובות הוא תרגול טוב ומפסיק אותך מ מעד על שמות קבצים המכילים שטח לבן (בין היתר). דוגמה: לאחר ביצוע a="x --help", נסה cat $a - זה ייתן לך את דף העזרה עבור cat. אז תנסה cat "$a" - זה יהיה (בדרך כלל) לומר cat: x --help: No such file or directory. בקיצור, לצטט מוקדם לצטט לעתים קרובות ואתה כמעט לא מתחרט על זה. - Score_Under


בשא, כאשר אתה לא מודאג עם הטלטלות פגזים שאינם תומכים בו, אתה תמיד צריך להשתמש תחביר כפול סוגר:

כל אחד מהבאים:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

בבאש, באמצעות סוגריים מרובעים כפולים, הציטוטים אינם נחוצים. ניתן לפשט את הבדיקה עבור משתנה זה עושה להכיל ערך ל:

if [[ $variable ]]

תחביר זה תואם ksh (לפחות ksh93, בכל מקרה). זה לא עובד טהור POSIX או מבוגר בורג פגזים כגון sh או מקף.

ראה התשובה שלי כאן ו Bashfaq / 031 לקבלת מידע נוסף על ההבדלים בין סוגריים מרובעים כפולים.

ניתן לבדוק אם משתנה מסוים אינו מוגדר (להבדיל ממחרוזת ריקה):

if [[ -z ${variable+x} ]]

שבו "x" הוא שרירותי.

אם אתה רוצה לדעת אם משתנה הוא null אך לא unset:

if [[ -z $variable && ${variable+x} ]]

227
2018-02-25 03:37



זה if [[ $variable ]] עבד בשבילי, ואפילו לא צריך את זה set -u אשר נדרש על ידי אחד הפתרונות המוצעים האחרים. - Teemu Leisti
אני חושב שזה יותר טוב מאשר התשובה המקובלת. - qed
למה אתה ממליץ על תכונה לא נייד כאשר עושה זאת לא נותן שום תועלת? - Alastair Irvine
@AlastairIrvine: אני מזכיר ניידות במשפט הראשון של התשובה שלי, את השאלה ואת הכותרת הגוף מכילים את המילה "בש" ואת השאלה מתויג באש, ואת מבנה סוגר כפול מספק יתרונות ברורים בדרכים רבות. ואני לא ממליץ לערבב סגנונות בסוגריים עקב עקביות ותחזוקה. אם אתה צריך מקסימום, הנמוך ביותר מכנה משותף הטלטלות, להשתמש sh במקום בש. אם אתה צריך את היכולות גדל כי הוא מספק, להשתמש Bash ולהשתמש בו במלואו. - Dennis Williamson
@BrunoBronosky: אני חזרתי לערוך. אין צורך ; בסופו של דבר. ה then יכול להיות בשורה הבאה ללא נקודה פסיק בכלל. - Dennis Williamson


משתנה באש (וכל פגז תואם POSIX) יכול להיות באחת משלוש מדינות:

  • לא מוגדר
  • על המחרוזת הריקה
  • מוגדר למחרוזת שאינה ריקה

רוב הזמן אתה רק צריך לדעת אם משתנה מוגדר מחרוזת לא ריקה, אבל מדי פעם חשוב להבחין בין unset ולהגדיר את המחרוזת הריקה.

להלן דוגמאות של איך אתה יכול לבדוק את האפשרויות השונות, וזה עובד bash או כל פגז תואם POSIX:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

הנה אותו דבר אבל בטופס שולחן שימושי:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

ה ${VAR+foo} מבנה מתרחב למחרוזת הריקה אם VAR הוא unset או foo אם VAR מוגדר לכל דבר (כולל מחרוזת ריקה).

ה ${VAR-foo} מבנה מתרחב לערך של VAR אם מוגדר (כולל מוגדר למחרוזת הריקה) foo אם לא מוגדר. אפשרות זו שימושית עבור מתן ברירות מחדל מוגזמות למשתמש (למשל, ${COLOR-red} אומר להשתמש red אלא אם כן המשתנה COLOR כבר מוגדר למשהו).

הסיבה למה [ x"${VAR}" = x ] מומלץ לעתים קרובות לבדוק אם משתנה הוא או לא מוגדר או להגדיר את המחרוזת הריקה היא כי כמה יישומים של [ (הידוע גם בשם test) הם באגי. אם VAR הוא מוגדר למשהו כמו -n, אז כמה יישומים יעשה את הדבר הלא נכון כאשר נתון [ "${VAR}" = "" ] כי הטיעון הראשון [ מתפרשת בטעות כ -n מפעיל, לא מחרוזת.


205
2018-04-24 20:39



בדיקת משתנה המוגדר למחרוזת הריקה יכולה להיעשות גם באמצעות [ -z "${VAR-set}" ]. - nwellnhof
@nwellnhof: תודה! עדכנו את תשובתי להשתמש בתחביר הקצר. - Richard Hansen
@ FaheemMitha: זה לא אשמתך - התשובה שלי היה קשה לקריאה. הוספתי שולחן בתקווה להפוך את התשובה ברורה יותר. - Richard Hansen
@RichardHansen: תודה, זוהי תוספת שימושית. - Faheem Mitha
בדיקות לא מסודרות אינן אמינות. אם המשתמש התקשר set -u או set -o nounset ב- bash, המבחן יוביל לשגיאה "bash: VAR: משתנה לא מאורגן". ראה stackoverflow.com/a/13864829 עבור בדיקה לא מסודרת יותר. שלי ללכת לבדוק אם משתנה הוא ריק או unset הוא [ -z "${VAR:-}" ]. ההמחאה שלי אם משתנה אינו ריק [ "${VAR:-}" ]. - Kevin Jin


-z היא הדרך הטובה ביותר.

אפשרויות נוספות בהן השתמשתי הוא להגדיר משתנה, אבל זה יכול להיות overridden על ידי משתנה אחר למשל

export PORT=${MY_PORT:-5432}

אם $MY_PORT משתנה הוא ריק, לאחר מכן PORT מקבל מוגדר 5432, אחרת PORT מוגדר לערך של MY_PORT. הערה התחביר כוללים את המעי הגס ואת מקף.


36
2018-06-11 13:19



מצאתי את זה היום בטעות, וזה בדיוק מה שרציתי. תודה! אני חייב לסבול set -o nounset בכמה תסריטים. - opello


אם אתה מעוניין להבחין בין המקרים של סטטוס ריק לעומת מצב לא מוגדר, בדוק את האפשרות -u עבור bash:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true

24
2018-05-12 18:21





אלטרנטיבה שראיתי [ -z "$foo" ] היא הבאה, עם זאת אני לא בטוח למה אנשים משתמשים בשיטה זו, מישהו יודע?

[ "x${foo}" = "x" ]

בכל מקרה, אם אתה disallowing משתנים unset (או על ידי set -u או set -o nounset), אז אתה תסתבך עם שתי שיטות אלה. יש לתקן את זה פשוט:

[ -z "${foo:-}" ]

הערה: פעולה זו תשאיר את המשתנה הלא מוגדר.


8
2017-10-20 03:58



יש תגובה על האלטרנטיבה -z ב pubs.opengroup.org/onlinepubs/009695399/utilities/test.html. בעיקרון, זה לא נועד להיות חלופה -z. במקום זאת, הוא מטפל במקרים שבהם $foo יכול להרחיב משהו מתחיל metacharacter כי [ או test יהיה מבולבל על ידי. לשים שרירותי שאינו metacharacter בתחילת מבטלת את האפשרות. - James Sneeringer


ה שאלה שואל כיצד לבדוק אם משתנה הוא מחרוזת ריקה ואת התשובות הטובות ביותר כבר ניתנו על זה.
אבל אני נחת כאן אחרי תקופה שעברה תכנות ב PHP ומה אני בעצם מחפש היה לבדוק כמו ריק פונקציה ב PHP עובד בתוך פגז bash.
אחרי שקראתי את התשובות הבנתי שאני לא חושב כראוי בבאש, אבל בכל מקרה באותו רגע פונקציה כמו ריק ב PHP היה שימושי soooo בקוד הבא שלי.
כפי שאני חושב שזה יכול לקרות לאחרים, החלטתי להמיר את php ריק פונקציה ב bash

על פי php ידניYou
משתנה נחשב ריק אם הוא אינו קיים או אם ערכו הוא אחד מאלה:

  • "" (מחרוזת ריקה)
  • 0 (0 כמספר שלם)
  • 0.0 (0 כמו לצוף)
  • "0" (0 כמחרוזת)
  • מערך ריק
  • הכריז על משתנה, אך ללא ערך

כמובן ריק ו שקר מקרים לא ניתן להמיר ב באש, ולכן הם מושמטים.

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



דוגמה לשימוש:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



הדגמה:
קטע הטקסט הבא:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

תפוקות:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty

אחרי שאמרתי את זה בבסיס ההיגיון בדיקות על אפס בתפקוד זה יכול לגרום לבעיות בצד imho, כל מי משתמש בפונקציה זו צריך להעריך את הסיכון הזה ואולי להחליט לחתוך את הבדיקות האלה עוזב רק הראשון.


6
2017-08-31 20:11



בתוך הפונקציה empty למה כתבת [[ $( echo "1" ) ]] ; return במקום פשוט return 1 ? - Dor


את כל אם אז ו- Z הם מיותרים.

["$ foo"] & הד "foo אינו ריק"
["$ foo"] || הד "foo הוא אכן ריק"

5
2018-01-26 14:02



זה ייכשל אם foo מכיל רווחים בלבד - Brian
יהיה גם להיכשל בכמה פגזים אם foo מתחיל עם מקף מאז הוא מתפרש כאפשרות. למשל על סולאריס ksh, zsh ו באש אין בעיה, sh ו / bin / הבדיקה ייכשל - ktf


זה נכון בדיוק כאשר $ FOO מוגדר וריק:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]

4
2018-05-20 20:52