เครื่องหมายวงเล็บในเงื่อนไข if: เหตุใดฉันจึงได้รับข้อผิดพลาดทางไวยากรณ์โดยไม่มีช่องว่าง


17

ฉันใช้สคริปต์ด้านล่างเพื่อย้ายสองวันกลับเมื่อสคริปต์ทำงานที่เริ่มต้นสองวันของปีและตรวจสอบวันแรกและวันที่สองของทุกเดือนและย้ายกลับสองวัน

if [$month="01"] && [$day="01"];
then
    date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
if [$month="01"] && [$day="02"];
then
         date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
   if [ $day = "01" ];
then
    date="$last_month/$yes_day/$year"
            fulldate="$year$last_month$yes_day"
else
        if [ $day = "02" ];
then
    date="$last_month/$yes_day/$year"
        fulldate="$year$last_month$yes_day"
else
    date="$month/$yes_day/$year"
        fulldate="$year$month$yes_day"
                fi
               fi
              fi
fi

แต่ฉันไม่ดีได้รับข้อความแสดงข้อผิดพลาดด้านล่าง

Etime_script.sh: line 19: [06=01]: command not found
Etime_script.sh: line 24: [06=01]: command not found

1
คำตอบที่ได้รับนั้นถูกต้อง [คุณต้องการช่องว่างหลัง นอกจากนี้ให้ดูที่elifคำสั่ง มันจะช่วยให้คุณทำความสะอาดสิ่งต่าง ๆ นอกจากนี้เครื่องหมายอัฒภาคหลังจากคำสั่ง if ไม่จำเป็น แต่ก็ไม่ถูกต้องเช่นกัน
Shawn J. Goff

@ ShawnJ.Goff พวกเขาจำเป็นถ้าคุณต่อบรรทัดถัดไป ( if [ ... ]; then) ดังนั้นจึงไม่ใช่เรื่องผิดปกติ
goldilocks

@ goldilocks ใช่นั่นคือสไตล์ที่ฉันชอบ เหตุผลที่ผิดปกติก็เพราะเขาไม่ได้ทำอย่างนั้น
Shawn J. Goff

คำตอบ:


27

[ไม่ใช่ metacharacter หรือตัวดำเนินการควบคุม (ไม่ใช่คำที่สงวนไว้; เหมือนกัน]) จึงต้องการช่องว่างรอบ ๆ มิฉะนั้นเปลือก "เห็น" คำสั่ง[01=01]แทนคำสั่ง[กับพารามิเตอร์แยกต่างหาก01, =, และ01 ]แต่ละโอเปอเรเตอร์และโอเปอแรนด์จะต้องเป็นอาร์กิวเมนต์ที่แยกต่างหากสำหรับ[คำสั่งดังนั้นช่องว่างจำเป็นสำหรับโอเปอเรเตอร์เช่นกัน

if [ "$month" = "01" ]

[$month="01"]เป็นรูปแบบการจับคู่สัญลักษณ์ใด ๆ ของตัวละครในหรือ$month "01ถ้ามันไม่ตรงกับอะไรเลย

หากมีเครื่องหมายอัฒภาคหลังจากวงเล็บปิดคุณไม่ต้องการช่องว่างก่อนหน้าเพราะเครื่องหมายอัฒภาคนั้นเป็นส่วนหนึ่งของโทเค็นที่แยกต่างหากเสมอ

if [ "$month" = "01" ]; then

เช่นเดียวกันสำหรับไวยากรณ์ของเครื่องหมายวงเล็บเหลี่ยมคู่ (และ ksh's และ zsh's)

มากกว่าหนึ่งเงื่อนไข

มีสองวิธีในการรวมเงื่อนไข:

  1. ภายใน [

  2. ด้วย[คำสั่งแยกต่างหากรวมกับ&&หรือ||

[การจัดกลุ่มที่มีวงเล็บคืออาจจะง่ายภายใน

if [ "$month" = "01" -a "$day" = "01" ] # -a for and, -o for or

if [ "$month" = "01" ] && [ "$day" = "01" ]

ควรหลีกเลี่ยงสิ่งแรกเนื่องจากไม่น่าเชื่อถือ (ลองใช้กับmonth='!') ปัญหาเกี่ยวกับเนื้อหาตัวแปรแปลก ๆ สามารถหลีกเลี่ยงได้โดยใช้สตริงที่ปลอดภัย (ถ้ามี) ก่อน หรือโดยใช้[[/ ]]แทน[/ ]:

if [ "01" = "$month" -a "01" = "$day" ]

วิธีที่เราสามารถจับคู่กับเงื่อนไขสองข้อในเช่นถ้าชอบค่าเดือน == ค่าวันหาก [$ month = "01"] && [$ day = "01"]; คาดว่าจะ 01 && 01 จริงแล้วพิมพ์เงื่อนไขด้านล่างหรือย้ายไปที่คำสั่งอื่น
กุมาร

@ShokSanganahalli ฉันได้ขยายคำตอบของฉัน
Hauke ​​Laging

1
[เมื่อ-a/ -oไม่ได้ใช้จะเชื่อถือได้เสมอกับเชลล์ที่สอดคล้องกับ POSIX ไม่มีสิ่งใด ๆ ในการใช้ประโยชน์เป็นมากกว่า-a/-o &&/||แน่นอนฉันจะไม่สนับสนุนการใช้งาน โปรดทราบว่า[[ไม่ใช่ POSIX
Stéphane Chazelas

4

อีกวิธีในการเขียน:

case $month:$day in
  (01:0[12])
    date="$last_month/$yes_day/$last_year"
    fulldate="$last_month/$yes_day/$last_year"
    ;;
  (*:0[12])
    date="$last_month/$yes_day/$year"
    fulldate="$year$last_month$yes_day"
    ;;
  (*)
    date="$month/$yes_day/$year"
    fulldate="$year$month$yes_day"
esac

1
+1 สำหรับcaseข้อความสั่ง หากคุณมีมากกว่าหนึ่งคุณอาจจะใช้elif case
HalosGhost

-1

ดังนั้นนี่คือคำตอบของคุณ:

if [ $var1 == $var2 ];
 then
    echo "bla bla"
fi

ดังนั้นคุณต้องใส่ "ช่องว่าง" ระหว่างวงเล็บเหลี่ยมและตัวแปร / ค่า


ไม่ฉันเดาเพราะตามที่ฉันขอให้สคริปต์เลื่อนกลับสองวันเมื่อสคริปต์ทำงานที่เริ่มต้นสองวันของปีและตรวจสอบวันแรกและวันที่สองของทุกเดือนและย้ายกลับสองวันหมายความว่าที่นี่ถ้า [$ month = "01"] && [$ day = "01"] เราคาดว่าจะจับคู่เดือน "01" และวันแรก "01" จริงย้ายไปแล้วหรือย้ายไปยังเงื่อนไขอื่น
Kumar1

1
@AshokSanganahalli: ฉันไม่รู้ว่ามันเกี่ยวข้องอย่างไร แต่เงื่อนไข IF ของคุณไม่ทำงานเพราะคุณไม่มี "ช่องว่าง" ระหว่างวงเล็บเหลี่ยมและค่า
Neven

@ShokSanganahalli โดยปกติแล้วมันไม่ใช่ความคิดที่ดีสำหรับคนในระดับทักษะของคุณที่จะโต้แย้งการแก้ไขจากคนที่มีความเข้าใจที่ดีขึ้นอย่างเห็นได้ชัดโดยไม่ต้องลองทำ หากการเดาของคุณถูกต้องคุณจะไม่ต้องถามที่นี่ใช่ไหม?
Hauke ​​Laging

4
-1 ไม่ใช่อ้างตัวแปรและการใช้แทนมาตรฐาน== =
Stéphane Chazelas

2
คำถามไม่ได้ติดแท็ก bash ผู้ประกอบการเปรียบเทียบความเท่าเทียมกันในมาตรฐาน[หรือที่รู้จักtestคำสั่ง=คือ [ถ้าสำหรับการทดสอบมันไม่ได้ทำการมอบหมายใด ๆ ดังนั้นจึงไม่จำเป็นต้องแก้ปัญหา [การใช้งานบางอย่างรองรับ==เป็นส่วนขยายของมาตรฐาน แต่ไม่ทั้งหมด The Bourne เปลือกของash's, poshs' [s หรือ/bin/[ระบบบางอย่างเช่นไม่ได้ ==ถูกเพิ่มโดยkshฉันคิดว่าสำหรับความสอดคล้องกับตัวดำเนินการเดียวกันในโครงสร้างใหม่(( ... ))(ซึ่งมีทั้ง = และ == แต่ไม่มีมาตรฐาน)
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.