Làm cách nào tôi có thể tách một lệnh shell trên nhiều dòng khi sử dụng câu lệnh IF?


385

Làm thế nào tôi có thể chia một lệnh trên nhiều dòng trong shell, khi lệnh là một phần của ifcâu lệnh?

Những công việc này:

if ! fab --fabfile=.deploy/fabfile.py --forward-agent --disable-known-hosts deploy:$target; then rc=1                                                                       
fi

Điều này không hoạt động:

# does not work:
if ! fab --fabfile=.deploy/fabfile.py \ 
  --forward-agent \
  --disable-known-hosts deploy:$target; then   
  rc=1
fi

Thay vì thực thi toàn bộ lệnh, tôi nhận được:

./script.sh: line 73: --forward-agent: command not found

Quan trọng hơn, những gì còn thiếu từ sự hiểu biết của tôi về Bash sẽ giúp tôi hiểu vấn đề này và những vấn đề tương tự trong tương lai?


2
Lỗi là gì? Tôi có thể thực thi $ if ! cp -n log/server1.log \ > .; then echo no copy; fimà không gặp lỗi, với một dòng mới sau\
Biến

15
Bạn có không gian sau dấu gạch chéo thiết bị đầu cuối \ ? Chúng khá khó nhìn. Nếu bạn làm như vậy, bạn có thể muốn xem liệu bạn có thể làm cho trình soạn thảo của mình xóa các dấu cách hoặc làm cho chúng rõ hơn không.
msw

10
Vâng, đó là khoảng trắng sau dấu gạch chéo đầu cuối. Tổng cộng. Cảm ơn bạn.
Dmitry Minkovsky

Và vâng, xin lỗi, tôi nên đăng "lỗi" (kết quả không mong muốn)! Lỗi của tôi! Chỉnh sửa ngay.
Dmitry Minkovsky

Sự hiểu biết của bạn là gì? Nó cũng không phải là một phần của câu hỏi.
hakre

Câu trả lời:


567

Tiếp tục dòng sẽ thất bại nếu bạn có khoảng trắng (khoảng trắng hoặc ký tự tab) sau dấu gạch chéo ngược và trước dòng mới. Không có khoảng trắng như vậy, ví dụ của bạn hoạt động tốt với tôi:

$ cat test.sh
if ! fab --fabfile=.deploy/fabfile.py \
   --forward-agent \
   --disable-known-hosts deploy:$target; then
     echo failed
else
     echo succeeded
fi

$ alias fab=true; . ./test.sh
succeeded
$ alias fab=false; . ./test.sh
failed

Một số chi tiết được quảng bá từ các bình luận: dấu gạch chéo ngược dòng trong vỏ không thực sự là một trường hợp đặc biệt; nó chỉ đơn giản là một ví dụ của quy tắc chung rằng dấu gạch chéo ngược "trích dẫn" ký tự theo sau ngay lập tức, ngăn chặn mọi xử lý đặc biệt mà nó thường phải tuân theo. Trong trường hợp này, nhân vật tiếp theo là một dòng mới, và điều trị đặc biệt đang được ngăn chặn là chấm dứt lệnh. Thông thường, một nhân vật được trích dẫn cuộn lên bao gồm cả nghĩa đen trong lệnh; thay vào đó, một dòng mới bị gạch chéo được xóa hoàn toàn. Nhưng nếu không, cơ chế là như nhau. Và dấu gạch chéo ngược chỉ trích dẫn ký tự theo sau; nếu ký tự đó là khoảng trắng hoặc tab, bạn chỉ cần lấy một khoảng trắng hoặc tab được trích dẫn và bất kỳ dòng mới nào tiếp theo vẫn không được trích dẫn.


5
Mark, bạn biết đấy, tôi phải có khoảng trắng. Tôi chỉ có thể tái tạo lỗi khi thêm khoảng trắng sau `s. For example, when adding one after the first `, tôi nhận được ./soundops: line 73: --forward-agent: command not found. Vấn đề của tôi là tôi đã không hiểu lỗi này. Tại sao có một khoảng trắng dẫn đến lỗi đó? Khoảng trắng + \n"phủ định" `` và phân định một lệnh?
Dmitry Minkovsky

84
Dấu gạch chéo ngược phía trước dòng mới ngăn dòng mới kết thúc lệnh. Nhưng cũng giống như các chuỗi thoát đặc biệt như "\ n" chỉ hoạt động mà không có gì giữa dấu gạch chéo ngược và n, dấu gạch chéo-dòng mới chỉ hoạt động mà không có gì giữa dấu gạch chéo ngược và dòng mới.
Mark Reed

19
Hahaha wow, tất nhiên điều đó có ý nghĩa. Không bao giờ nhìn thấy nó theo cách đó. Mở mắt, nhưng rất đơn giản: nó chỉ là một dòng mới thoát. Tôi ghét những nhân vật vô hình. Chúng sẽ có ý nghĩa hơn đối với tôi nếu tất cả chúng chỉ hiển thị. Cảm ơn bạn!
Dmitry Minkovsky

7
Trong hầu hết các trình soạn thảo, bạn có thể hiển thị những ký tự vô hình đó.
lucasvc

1
Dấu gạch chéo ngược và dòng mới được xóa khỏi dòng lệnh hiệu quả, nhưng bất kỳ khoảng trắng hàng đầu nào trên dòng tiếp theo đều được giữ nguyên. Vì vậy, đó có phải là vấn đề hay không phụ thuộc vào việc khoảng trắng có phải là vấn đề tại thời điểm đó trong lệnh một dòng hay không.
Mark Reed

52

Đối với người dùng Windows / WSL / Cygwin, v.v.

Đảm bảo rằng các kết thúc dòng của bạn là nguồn cấp dữ liệu Unix tiêu chuẩn, tức là chỉ \n(LF).

Sử dụng kết thúc dòng Windows \r\n(CRLF) sẽ phá vỡ ngắt dòng lệnh.


Điều này là do có \ở cuối dòng có dòng Windows kết thúc dịch \ \r \n.
Như Mark giải thích chính xác ở trên:

Tiếp tục dòng sẽ thất bại nếu bạn có khoảng trắng sau dấu gạch chéo ngược và trước dòng mới.

Điều này bao gồm không chỉ khoảng trắng ( ) hoặc tab ( \t) mà còn cả lợi nhuận vận chuyển ( \r).


1
Điều này khắc phục sự cố được tạo khi tạo tập lệnh trong Windows và sau đó sử dụng tập lệnh đó trong Windows bash (ví dụ: bash -c MyShellScript.sh nơi MyShellScript.sh được tạo trong trình chỉnh sửa Windows). Bạn phải lưu MyShellScript.sh ở định dạng UNIX có thể sử dụng notepad ++.
BSalita
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.