שאלה מה ההבדל בין סוגריים מרובעים כפולים ומרובעים בבאש?


אני רק תוהה מה בדיוק ההבדל בין

[[ $STRING != foo ]]

ו

[ $STRING != foo ]

הוא, מלבד זה האחרון הוא תואם fusix, נמצא sh ו לשעבר הוא הרחבה נמצא bash.


347
2017-08-09 21:11




במקרה שאתה תוהה גם לגבי שימוש בסוגריים לא, בכלל. בהקשר של if הצהרה, ראה mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D - Kev
כמו כן, מתוך המסמכים של אובונטו: wiki.ubuntu.com/... - radistao


תשובות:


ישנם מספר הבדלים. לדעתי, כמה מן החשובים ביותר הם:

  1. [ הוא מובנה בבאש ופגזים מודרניים רבים אחרים. הבנין [ דומה ל test עם הדרישה הנוספת של סגירה ]. הבנויים [ ו test לחקות את הפונקציונליות /bin/[ ו /bin/test יחד עם המגבלות שלהם כך סקריפטים יהיה תואם לאחור. הרציפים המקוריים עדיין קיימים בעיקר עבור תאימות POSIX ותאימות לאחור. הפעלת הפקודה type [ ב Bash מציין את זה [ מתפרשת כברירת מחדל. (הערה: which [ רק מחפש הרצה על PathH והוא שווה ל type -p [)
  2. [[ הוא לא תואם, זה לא בהכרח לעבוד עם מה /bin/sh נקודות ל. לכן [[ היא אופציה מודרנית יותר של Bash / Zsh / Ksh.
  3. כי [[ הוא בנוי לתוך הקליפה ואין דרישות דור קודם, אתה לא צריך לדאוג פיצול מילה על בסיס IFS משתנה כדי בלגן על משתנים להעריך למחרוזת עם רווחים. לכן, אתה לא באמת צריך לשים את המשתנה במרכאות כפולות.

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

  1. אתה לא צריך לדאוג מצטט את הצד השמאלי של הבדיקה, כך שהוא למעשה מקבל לקרוא כמשתנה.
  2. אתה לא צריך לברוח פחות מאשר יותר < > עם backslashes כדי לא לקבל הערכה כמו ניתוב מחדש קלט, אשר באמת יכול לבלגן כמה דברים על ידי החלפת קבצים. זה שוב חוזר [[ להיות מובנה. אם [מבחן] הוא תוכנית חיצונית הקליפה יצטרך לעשות יוצא מן הכלל בדרך שבה הוא מעריך < ו > רק אם /bin/test הוא נקרא, אשר לא ממש הגיוני.

262
2017-08-09 21:56



תודה, הקישור לשאלות הנפוצות היה מה שחיפשתי (לא ידעתי על הדף הזה, תודה). - 0x89
ערכתי את הפוסט שלך עם מידע זה, אבל [ובדיקה מתבצעת כמו מובנית. הבנויים נועדו להחליף / bin / [ו / bin / test אבל צריך לשחזר את המגבלות של קבצים בינאריים מדי. הפקודה 'סוג [' 'מוודאת שהבניין משמש. 'אשר [' רק מחפש הרצה על PathH והוא שווה ל 'סוג -P [' - klynch


בקצרה:

[הוא באש מובנה

[[]] הם bash מילות מפתח

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

  $ [ a < b ]
 -bash: b: No such file or directory
  $ [[ a < b ]]

הדוגמה הראשונה מחזירה שגיאה מכיוון ש- bash מנסה לנתב מחדש את הקובץ b אל הפקודה [a]. הדוגמה השנייה בעצם עושה את מה שאתה מצפה לזה. התו <כבר לא יש משמעות מיוחדת של מפעיל מחדש את הקובץ.

מקור: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments


110
2017-12-29 19:42



[ היא פקודה פגז POSIX; זה לא צריך להיות מובנה. ] הוא רק טיעון שהפקודה מחפשת, כך שהתחביר מאוזן. הפקודה היא שם נרדף test חוץ מזה ש test לא מחפש סגר ]. - Kaz
ראה כאן: pubs.opengroup.org/onlinepubs/009695399/utilities/test.html - Kaz


הפרשי התנהגות

נבדק בבאש 4.3.11:

  • POSIX לעומת הרחבה באש:

  • פקודה רגילה לעומת הקסם - -

    • [ היא רק פקודה רגילה עם שם מוזר.

      ] הוא רק טיעון של [ המונע שימוש בטענות נוספות.

      אובונטו 16.04 למעשה יש הפעלה עבור זה ב /usr/bin/[ שסופקו על ידי coreutils, אבל לגרסה מובנית הבש יש עדיפות.

      שום דבר לא משתנה באופן שבו Bash מנתח את הפקודה.

      באופן מיוחד, < היא ניתוב מחדש, && ו || שרשור פקודות מרובות, ( ) מייצרת subshells אלא אם כן נמלט \, והרחבת מילים מתרחשת כרגיל.

    • [[ X ]] הוא מבנה אחד שעושה X יש לנתח בצורה קסומה. <, &&, || ו () מטופלים במיוחד, וכללי פיצול מילים שונים.

      יש גם הבדלים נוספים = ו =~.

    בבאשזית: [ היא מובנית הפקודה, ו [[ היא מילת מפתח: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword

  • <

  • && ו ||

    • [[ a = a && b = b ]]: נכון, הגיוני
    • [ a = a && b = b ]: שגיאת תחביר, && מנתח כמפריד פקודות של AND cmd1 && cmd2 
    • [ a = a -a b = b ]: שווה ערך, אך הוצא משימוש על ידי POSIX
    • [ a = a ] && [ b = b ]: המלצה POSIX
  • (

    • [[ (a = a || a = b) && a = b ]]: שקר
    • [ ( a = a ) ]: שגיאת תחביר, () מתפרשת כתת-זיקה
    • [ \( a = a -o a = b \) -a a = b ]: שווה ערך, אבל () הוא הוצא משימוש על ידי POSIX
    • ([ a = a ] || [ a = b ]) && [ a = b ] המלצה POSIX
  • פיצול מילים

    • x='a b'; [[ $x = 'a b' ]]: נכון, ציטוטים לא נחוץ
    • x='a b'; [ $x = 'a b' ]: שגיאת תחביר, מתרחב ל [ a b = 'a b' ]
    • x='a b'; [ "$x" = 'a b' ]youð
  • =

    • [[ ab = a? ]]: נכון, כי זה עושה התאמת תבנית (* ? [ הם קסם). לא גלגל להרחיב קבצים בספרייה הנוכחית.
    • [ ab = a? ]You a? גלובוס מתרחב. אז זה יכול להיות נכון או שקר בהתאם לקבצים בספרייה הנוכחית.
    • [ ab = a\? ]: שקר, לא הרחבה גלובלית
    • = ו == זהים בשניהם [ ו [[, אבל == הוא הרחבת Bash.
    • printf 'ab' | grep -Eq 'a.': שווה ערך POSIX ERE
    • [[ ab =~ 'ab?' ]]: שקר, מאבד עם הקסם ''
    • [[ ab? =~ 'ab?' ]]: נכון
  • =~

    • [[ ab =~ ab? ]]: נכון, POSIX ביטוי רגולרי מורחב התאמה, ? לא גלובוס להרחיב
    • [ a =~ a ]: שגיאת תחביר
    • printf 'ab' | grep -Eq 'ab?': שווה POSIX

המלצה

אני מעדיף להשתמש תמיד [].

יש שקילות POSIX עבור כל [[ ]] לבנות ראיתי.

אם אתה משתמש [[ ]] אתה:

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

63
2017-07-12 10:22



איך להישתמש printf 'ab' | grep -Eq 'ab?' בתוך if [ … ]? - meeDamian
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi. [] היא בדיוק כמו פקודה grep. ה () לא ייתכן שיהיה צורך על פקודה זו אני לא בטוח: הוספתי את זה בגלל |, תלוי איך Bash מנתח דברים. אם לא היה | אני בטוח שאתה יכול לכתוב רק if cmd arg arg; then. - Ciro Santilli 新疆改造中心 六四事件 法轮功
@meeDamian כן, אין צורך () נראה ש: stackoverflow.com/questions/8965509/... - Ciro Santilli 新疆改造中心 六四事件 法轮功
רשימה נחמדה! ראה גם: wiki.ubuntu.com/... - radistao


בהתבסס על קריאה מהירה של החלקים הרלוונטיים של manpage, ההבדל העיקרי נראה כי == ו != אופרטורים מתאימים נגד דפוס, ולא מחרוזת מילולית, וגם שיש את =~ מפענח השוואה.


4
2017-08-09 21:17





סוגר בודד כלומר [] הוא POSIX פגז תואם כדי להקיף ביטוי תנאי.

סוגריים כפולים כלומר [[]] היא גרסה משופרת (או הרחבה) של גרסה סטנדרטית POSIX, זה נתמך על ידי bash ופגזים אחרים (zsh, ksh).

בבאש, עבור השוואה מספריים אנו משתמשים eq, ne,lt ו gt, עם סוגריים כפולים להשוואה נוכל להשתמש ==, !=, <, ו > פשוטו כמשמעו.

  • [ הוא שם נרדף לפקודת הבדיקה. גם אם הוא בנוי לתוך פגז זה יוצר תהליך חדש.
  • [[ היא גרסה משופרת חדשה של זה, שהיא מילת מפתח, לא תוכנית.

לדוגמה:

[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory 
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works

3
2018-02-08 03:15