سؤال كيفية تحديد ما إذا كان متغير bash فارغًا؟


ما أفضل طريقة لتحديد ما إذا كان المتغير في bash فارغًا ("")؟

لقد سمعت أنه من المستحسن أن أفعل if [ "x$variable" = "x" ]

هل هذا هو صيح الطريقة؟ (يجب أن يكون هناك شيء أكثر وضوحًا)


721
2018-05-12 17:54


الأصل




الأجوبة:


سيؤدي هذا إلى إظهار true إذا لم يتم تعيين متغير أو تعيينه على السلسلة الفارغة ("").

if [ -z "$VAR" ];

986
2018-05-12 18:06



هل يشمل ذلك إذا كان المتغير IS SET بقيمة ""؟ - Brent
نعم يفعل ... "-z" اختبارات لسلسلة ذات طول صفري. - David Z
if [ ! -z "$VAR" ]; - Aaron Copley
معكوس -z هو -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


في Bash ، عندما لا تكون مهتمًا بقابلية نقل الأصداف التي لا تدعمها ، يجب دائمًا استخدام بنية القوس المزدوج:

اى من التالية:

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

في Bash ، باستخدام الأقواس المربعة المزدوجة ، لا تكون علامات الاقتباس ضرورية. يمكنك تبسيط الاختبار لمتغير ذلك هل تحتوي على قيمة ل:

if [[ $variable ]]

هذا التركيب متوافق مع ksh (على الأقل ksh93 ، على أي حال). لا تعمل في POSIX أو قذائف بورن أقدم مثل sh أو اندفاعة.

نرى جوابي هنا و BashFAQ / 031 لمزيد من المعلومات حول الاختلافات بين الأقواس المربعة المزدوجة والأخرى.

يمكنك اختبار لمعرفة ما إذا كان هناك متغير معين غير محدد (على أنه مميز عن سلسلة فارغة):

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

حيث يكون "x" تعسفيًا.

إذا كنت تريد معرفة ما إذا كان المتغير فارغًا أم لا ،

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

227
2018-02-25 03:37



أن if [[ $variable ]] عملت بشكل جيد بالنسبة لي ، ولم أكن بحاجة حتى set -u كان ذلك مطلوبًا من خلال أحد الحلول المقترحة الأخرى. - Teemu Leisti
أعتقد أن هذا أفضل من الإجابة المقبولة. - qed
لماذا توصي بميزة غير محمولة عند القيام بذلك لا يعطي أي فائدة؟ - Alastair Irvine
AlastairIrvine: أذكر قابلية النقل في الجملة الأولى من جوابي ، يحتوي عنوان السؤال والجسم على كلمة "Bash" ويتم وضع علامة على السؤال سحق، ويوفر هيكل قوس مزدوج مزايا واضحة بطرق عدة. وأنا لا أوصي بخلط أنماط السناد لأسباب الاتساق والصيانة. إذا كنت بحاجة إلى الحد الأقصى ، أقل قابلية القاسم المشترك ، استخدم sh بدلا من باش. إذا كنت بحاجة إلى زيادة القدرات التي يوفرها ، فاستخدم باش واستخدمها بالكامل. - Dennis Williamson
BrunoBronosky: لقد عادت التعديل. ليس هناك حاجة ل ; في نهايةالمطاف. ال then يمكن أن يكون على السطر التالي بدون فاصلة منقوطة على الإطلاق. - Dennis Williamson


يمكن أن يكون المتغير في bash (وأي shell متوافق مع POSIX) في إحدى الحالات الثلاث:

  • غير مصلد
  • لتعيين السلسلة الفارغة
  • لتعيين سلسلة غير فارغة

في معظم الأوقات ، تحتاج فقط إلى معرفة ما إذا كان المتغير قد تم تعيينه على سلسلة غير فارغة ، ولكن من المهم في بعض الأحيان التمييز بين التعيين والتعيين إلى السلسلة الفارغة.

فيما يلي أمثلة على كيفية اختبار الاحتمالات المختلفة ، وهي تعمل في bash أو أي shell متوافق مع 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 غير مخصص أو ل 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
@ ريتشارد هانسن: شكرًا لك ، هذه إضافة مفيدة. - Faheem Mitha
الشيكات غير المحددة ليست موثوقة. إذا دعا المستخدم set -u أو set -o nounset في bash ، فإن الاختبار سيؤدي فقط إلى الخطأ "bash: VAR: unound variable". نرى stackoverflow.com/a/13864829 للحصول على فحص غير موثوق أكثر موثوقية. بلدي الذهاب إلى التحقق من ما إذا كان متغير هو فارغ أو غير معين [ -z "${VAR:-}" ]. الشيك الخاص بما إذا كان المتغير غير فارغ [ "${VAR:-}" ]. - Kevin Jin


-z هي أفضل طريقة.

هناك خيار آخر قمت باستخدامه هو تعيين متغير ، لكن يمكن تغييره من خلال متغير آخر على سبيل المثال

export PORT=${MY_PORT:-5432}

إذا كان $MY_PORT متغير فارغ ، ثم PORT تعيين على 5432 ، وإلا يتم تعيين PORT إلى قيمة MY_PORT. لاحظ أن بناء الجملة يتضمن النقطتين وشرطة.


36
2018-06-11 13:19



وجدت هذا عن غير قصد هذا اليوم ، وكان بالضبط ما أردت. شكر! لا بد لي من تحمل set -o nounset في بعض النصوص. - opello


إذا كنت مهتمًا بالتمييز بين حالات set-empty مقابل unset status ، فابحث عن الخيار -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" ]

على أي حال إذا كنت عدم السماح لمتغيرات غير محدودة (إما عن طريق set -u أو set -o nounset) ، ثم تواجه مشكلة مع كل من هذه الأساليب. هناك حل بسيط لهذا:

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

ملاحظة: هذا سيترك المتغير undef الخاص بك.


8
2017-10-20 03:58



هناك تعليق حول البديل ل -z في pubs.opengroup.org/onlinepubs/009695399/utilities/test.html. في الأساس ، لا يقصد به أن يكون بديلاً عن -z. بدلا من ذلك ، فإنه يعالج الحالات فيها $foo يمكن أن تتوسع إلى شيء يبدأ بالحرف الأول [ أو test سيكون الخلط من قبل. وضع حرف غير مقرر تعسفي في البداية يزيل هذا الاحتمال. - James Sneeringer


ال سؤال يطلب كيفية التحقق مما إذا كان المتغير عبارة عن سلسلة فارغة وتم بالفعل تقديم أفضل الإجابات لذلك.
لكنني هبطت هنا بعد فترة مرت البرمجة في php وما كنت في الواقع البحث كان الاختيار مثل وظيفة فارغة في php العمل في قذيفة باش.
بعد قراءة الإجابات أدركت أنني لم أفكر بشكل صحيح في باش ، ولكن على أي حال في هذه اللحظة وظيفة مثل فارغة في php لكان soooo مفيد في بلدي bash code.
كما أعتقد أن هذا يمكن أن يحدث للآخرين ، فقد قررت تحويل وظيفة php الفارغة في bash

وفقا ل دليل php:
يعتبر متغير فارغًا إذا لم يكن موجودًا أو إذا كانت قيمته واحدة مما يلي:

  • "" (سلسلة فارغة)
  • 0 (0 كعدد صحيح)
  • 0.0 (0 كتعويم)
  • "0" (0 كسلسلة)
  • صفيف فارغ
  • أعلن متغير ، ولكن بدون قيمة

بالطبع لا شيء و خاطئة لا يمكن تحويل الحالات في bash ، لذا يتم حذفها.

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

بعد أن قال ذلك في منطق bash فإن الشيكات على الصفر في هذه الوظيفة يمكن أن تسبب مشاكل جانبية imho ، أي شخص يستخدم هذه الوظيفة يجب أن يقيّم هذا الخطر وربما يقرر أن يقطع هذه الشيكات ليترك فقط أولها.


6
2017-08-31 20:11



داخل الوظيفة empty - لماذا كتبت [[ $( echo "1" ) ]] ; return بدلا من ببساطة return 1 ؟ - Dor


كامل if-then و -z غير ضرورية.

["$ foo"] && echo "foo is not empty"
["$ foo"] || صدى "فو هو في الواقع فارغة"

5
2018-01-26 14:02



سوف تفشل إذا احتوت فو على مساحات فقط - Brian
سوف تفشل أيضا في بعض القذائف إذا فو يبدأ بشرطة منذ أن يتم تفسيرها كخيار. مثلا على سولاريس KSH، zsh و سحق لا توجد مشكلة ، ش و / بن / اختبار سوف تفشل - ktf


هذا صحيح تمامًا عندما يتم تعيين FOO $ وفارغ:

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

4
2018-05-20 20:52





شخصيا تفضل طريقة أكثر وضوحا للتحقق:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi

4
2017-12-09 15:15



بعض القذائف لا تقبل علامة المساواة المزدوجة. - Dennis Williamson
كان السؤال عن باش. أنا أستخدم باش. يعمل بشكل جيد بالنسبة لي. ما الذي تتحدثين عنه بالضبط؟ - Fedir RYKHTIK
إذا كنت تستخدم Bash ، فيجب استخدام قوسين مربعين. كان تعليقي السابق عبارة بسيطة للحقائق بالنسبة لأولئك الذين قد يقرؤون إجابتك ويكون استخدام قذيفة مختلفة. - Dennis Williamson
بين قوسين مربعين على ما يرام في هذه الحالة ، يرجى الاطلاع serverfault.com/questions/52034/... - Luca Borrione


تمديد oneliner من duffbeer703الحل:

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter

3
2017-08-31 11:34