nếu, elif, vấn đề tuyên bố khác trong Bash


358

Tôi dường như không thể tìm ra vấn đề với iftuyên bố sau đây liên quan đến elifthen. Hãy nhớ rằng printfvẫn còn đang được phát triển Tôi chỉ chưa thể kiểm tra nó trong tuyên bố nên nhiều khả năng là sai.

Lỗi tôi nhận được là:

./timezone_string.sh: line 14: syntax error near unexpected token `then'
./timezone_string.sh: line 14: `then'

Và tuyên bố là như vậy.

if [ "$seconds" -eq 0 ];then
   $timezone_string="Z"
elif[ "$seconds" -gt 0 ]
then
   $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
else
   echo "Unknown parameter"
fi

7
Tôi tự hỏi tại sao chúng ta cần các thentuyên bố trong ifelifnhưng không phải trong else, và cũng có thể nói chung.

@ w17t, vì chúng ta cần tách điều kiện khỏi chuỗi.
Sasha

3
@codeforester Tôi không thấy nhiều logic khi đánh dấu câu hỏi 500 nghìn lượt xem là trùng lặp với câu hỏi chỉ có 5K
fedorqui 'SO dừng làm hại'

Sử dụng một số công cụ định dạng tự động mã có thể giúp bạn bằng cách tự động thêm / xóa khoảng trắng xung quanh dấu ngoặc. Bạn có thể tìm kiếm các plugin cho trình soạn thảo của mình.
Nj Subedi

Câu trả lời:


453

Có một khoảng trống bị thiếu giữa elif[:

elif[ "$seconds" -gt 0 ]

nên là

elif [ "$seconds" -gt 0 ]

Như tôi thấy câu hỏi này đang nhận được rất nhiều lượt xem, điều quan trọng là chỉ ra rằng cú pháp cần tuân theo là:

if [ conditions ]
# ^ ^          ^

có nghĩa là không gian là cần thiết xung quanh dấu ngoặc . Nếu không, nó sẽ không hoạt động. Điều này là do [bản thân nó một lệnh.

Lý do tại sao bạn không nhìn thấy cái gì đó như elif[: command not found(hoặc tương tự) là sau khi nhìn thấy ifthen, vỏ đang tìm kiếm một trong hai elif, elsehoặc fi. Tuy nhiên, nó tìm thấy một cái khác then(sau khi định dạng sai elif[). Chỉ sau khi đã phân tích cú pháp, nó sẽ được thực thi (và một thông báo lỗi như elif[: command not foundsẽ được xuất ra).


33
Lý do các dấu ngoặc cần khoảng trắng là vì chúng chỉ là các phím tắt cho các chương trình thực tế (ít nhất là dấu ngoặc đầu tiên, dấu ngoặc thứ hai chỉ là cú pháp đường như tôi hiểu). Để hiểu ý nghĩa của nó, hãy xem trang chủ thực tế cho khung bên trái:$ man [
Michael Johansen

3
Có phải bài đăng này không được coi là đóng lỗi chính tả?
zx8754

3
@ zx8754 có thể đã có, nhưng nó không trở thành một cách chuẩn để sửa lỗi này, điều này có vẻ khá hữu ích (360K lượt xem và đếm).
fedorqui 'SO ngừng làm hại'

3
Một số đồng nghiệp của tôi không hiểu khái niệm "không gian" hoặc "phong cách mã hóa" nên đây có thể không phải là một lỗi đánh máy.
juzzlin

3
[là một loại bí danh cho lệnh kiểm tra. Đây là lý do tại sao các ký tự trống được yêu cầu. if test "$seconds" -eq 0; then ... fitương đương với if [ "$seconds" -eq 0 ];then ... fi ]. @LeiYang man testlà những gì bạn thực sự tìm kiếm
Melicerte

303

Bạn có một số vấn đề cú pháp với kịch bản của bạn. Đây là một phiên bản cố định:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi

76
Thật kỳ lạ, đây là cấu trúc "nếu-thì-khác" hoàn chỉnh và đơn giản bash mà tôi dễ dàng tìm thấy trên stackexchange ... cảm ơn.
tự đại diện

1
thụt đầu dòng là tùy chọn. thông dịch viên có thể (và nên) #!/bin/sh.

3
@ Chinggis6 Tổng số vô nghĩa, thông dịch viên thể #!/bin/shnhưng không phải.
Camusensei

4
@Camusensei nó không phải là một tổng vô nghĩa như shcó thể được sử dụng thay cho khả năng tương thích cao hơn (không phải tất cả * distro nix có bash như vỏ mặc định (một số có ksh hoặc tro nhưng hầu hết trong số họ phụ thuộc vào tiêu chuẩn shchức năng). Hơn nữa nếu cụ thể của bash hoặc các tính năng nâng cao không được sử dụng trong tập lệnh thì 'sh' nên được sử dụng làm trình thông dịch (một lý do nữa cho nó) vì nó có thể tự xử lý tập lệnh.

6
@ Chinggis6 Đúng, lựa chọn từ ngữ xấu về phía tôi.
Camusensei

25

[là một lệnh (hoặc tích hợp trong một số shell). Nó phải được phân tách bằng khoảng trắng từ câu lệnh trước:

elif [

3
Nó được bổ sung bởi một nội dung tích hợp trong bash, nhưng thông điệp của bạn vẫn đúng. sử dụng type -a [để thấy rằng
Camusensei

Nó cũng là một thứ nhị phân luôn có vẻ kỳ lạ đối với tôi.
mr.zog

4

Tôi muốn giới thiệu bạn có một cái nhìn cơ bản về điều hòa trong bash.

Biểu tượng "[" là một lệnh và phải có khoảng trắng trước nó. Nếu bạn không cung cấp khoảng trắng sau elif của mình, hệ thống sẽ giải thích elif [ như một lệnh cụ thể chắc chắn không phải là điều bạn muốn vào lúc này.

Sử dụng:

elif(A COMPULSORY WHITESPACE WITHOUT PARENTHESIS)[(A WHITE SPACE WITHOUT PARENTHESIS)conditions(A WHITESPACE WITHOUT PARENTHESIS)]

Nói tóm lại, hãy chỉnh sửa đoạn mã của bạn thành:

elif [ "$seconds" -gt 0 ]

Bạn sẽ ổn mà không có lỗi biên dịch. Phân đoạn mã cuối cùng của bạn sẽ trông như thế này:

#!/bin/sh    
if [ "$seconds" -eq 0 ];then
       $timezone_string="Z"
    elif [ "$seconds" -gt 0 ]
    then
       $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
    else
       echo "Unknown parameter"
    fi

2

Thiếu không gian giữa elif[phần còn lại chương trình của bạn là chính xác. bạn cần sửa nó và kiểm tra xem nó ra. đây là chương trình cố định:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi

liên kết hữu ích liên quan đến bash này nếu tuyên bố khác

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.