Điều gì tương đương với && khi viết tập lệnh bash?


31

Tôi xin lỗi trước nếu đây là một câu hỏi trùng lặp. Tôi đã nỗ lực tìm kiếm / kiểm tra trước khi hỏi ở đây.

Tôi cảm thấy thoải mái với việc viết một lớp như thế này:

foocommand && foocommand2 && foocommand3

Ý tưởng là tôi chỉ muốn các lệnh tiếp theo chạy nếu lệnh trước đó "thành công".

Tôi đang viết một đoạn script hơi dài và đoạn mã này không khả thi vì nó trông giống như một khối mã lớn gây nhầm lẫn cho những người khác.

Tôi muốn loại bỏ các lệnh và viết bình luận giữa chúng trong kịch bản. Làm cách nào tôi có thể làm điều này mà vẫn có tương đương với && trong đó?


4
Gấu này lặp đi lặp lại: &&không có nghĩa là lệnh tiếp theo sẽ chạy nếu trước đó một đã thành công. Nó có nghĩa là lệnh sẽ chạy nếu kết quả chung của tất cả các lệnh trước đó trong danh sách lệnh là thành công. Bạn có thể biết điều này, nhưng độc giả tương lai có thể hiểu sai.
kojiro

1
Cũng giống như một ghi chú, hành vi này bạn mô tả xuất phát từ ||&&(trái ngược với |hoặc &) được gọi là ngắn mạch. Hành vi được sử dụng với các toán tử sau được gọi là đánh giá háo hức.
AndyPerinf

7
@kojiro: Tôi không thấy sự khác biệt. a && b && csẽ chỉ chạy bnếu athành công, vì vậy "nó chỉ chạy cnếu bthành công" và "nó chỉ chạy cnếu abcả hai thành công" là những tuyên bố tương đương: bkhông thể thành công trừ khi athành công.
ruakh

1
@ruakh a || b && cmang tính minh họa hơn.
kojiro

8
@ruakh không, true || false && echo hisẽ xuất hi. Thông số kỹ thuật đọc, Toán tử "&&" và "||" sẽ có quyền ưu tiên như nhau và sẽ được đánh giá với tính kết hợp trái.
kojiro

Câu trả lời:


23

Bạn có thể làm như thế này:

#!/bin/sh
ls -lh &&
    # This is a comment
    echo 'Wicked, it works!'

Tôi hy vọng tôi hiểu những gì bạn hỏi chính xác.


Cảm ơn. Đây là gần nhất với những gì tôi đã hy vọng để làm. Và nó làm cho nó rất dễ dàng để chuyển đổi trở lại thành một lớp lót nếu cần thiết.
Mike B

Mike, vì bạn lo ngại về độ sạch của mã, nên một quy ước chung là thụt vào các phần 2 N của chuỗi bên dưới phần đầu tiên.
jblaine

@jblaine Tôi không chắc là tôi hiểu ý của bạn. Bạn có thể vui lòng giải thích?
Mike B

Mike, Stackexchange sẽ không cho phép tôi định dạng câu trả lời của mình một cách chính xác, vì vậy đây là tất cả những gì tôi muốn nói: thụt lề
jblaine

@jblaine Điểm tốt, chỉnh sửa để thụt dòng.
Volker Siegel

38

Bạn có thể thay đổi dòng shebang thành

#!/bin/bash -e

Sau bất kỳ lỗi nào, tập lệnh sẽ dừng lại.


1
Hấp dẫn. Tôi sẽ ghi nhớ điều đó. Cảm ơn bạn.
Mike B

cứu tôi khỏi việc gõ set -e khi tôi cần
Silverrocker

@Silverrocker Đó là POSIX (trừ bashphần tất nhiên). Shell POSIX có một loạt các tùy chọn áp dụng cho set. Hoặc ngược lại? setlà một cách để thiết lập các tùy chọn dòng lệnh shell trong tập lệnh.
Kaz

7
Thật không may, có một số tiện ích tiêu chuẩn không tuân theo các quy ước về trạng thái thoát thông thường, do đó -ecó thể hoạt động sai. Ví dụ: có thể bạn không muốn tập lệnh của mình chấm dứt mỗi khi diffhai tệp không giống nhau. Tất nhiên, bạn có thể giải quyết vấn đề này bằng cách nối thêm || true(hoặc có thể || [ $? = 1 ]) vào các lệnh như vậy, nhưng OP đề cập đến "mọi người khác" sẽ phải đọc tập lệnh này và nói "mọi người khác" có thể sẽ không quen với việc phải đối phó với -e.
ruakh

4
Tôi đã từng đưa -ecô ấy vào, cho đến khi một quản trị viên của công ty tôi tiếp tục khởi chạy các tập lệnh của tôi bash myscript.sh, vì vậy nó đã bỏ qua -e. Bây giờ tất cả các kịch bản của tôi có một set -edòng thứ hai.
Carlos Campderrós

19

Nếu bạn không thích set -eý tưởng, có lẽ bạn có thể đảo ngược logic.

foocommand || exit 1
foocommand2 || exit 2
foocommand3 || exit 3

exitHữu ích hơn, thay thế bằng một cái gì đó để in một thông báo lỗi hữu ích, sau đó thoát. Bên trong một chức năng, tất nhiên, bạn muốn returnthay vì exit.


11
Hoặc foocommand || exitđể thoát với foocommandtrạng thái thoát nếu khác không.
Stéphane Chazelas

Cái này hoạt động ra sao? Có giống như trong C - nếu đối số bên trái ước lượng thành TRUE, thì không có thêm đối số nào được kiểm tra?
Vorac

Vâng đúng vậy. Đó là một thành ngữ phổ biến trong Lisp (và các ngôn ngữ chức năng nói chung, tôi cho rằng) và trong Perl.
tripleee 30/03/13

9

Bạn có thể sử dụng if else ficác khối thay thế.

if foocommand; then

  # some comments

  if foocommand2; then

    # more comments

    foocommand3
  fi
fi

Nó dễ đọc hơn một chút.

Ngoài ra, bạn chỉ có thể sử dụng \để chia lớp 1 lớn của bạn thành nhiều dòng

foocommand && \
  # some comment
  foocommand2 && \
    # more comment
    foocommand3

Nhưng tất nhiên điều này có thể gây nhầm lẫn cho mắt chưa được huấn luyện.


4
Tôi không nghĩ rằng điều đó \là cần thiết ở đó.
Phường Samuel Edwin

Bạn đúng rồi. Thói quen của lực lượng.
Martín Canaval

5

Bạn có thể xem xét sử dụng các ifbáo cáo lồng nhau . Tùy chọn khác là sử dụng xoăn để nhóm như{ true && echo hi; } || echo huh

Cập nhật 1:

Đây là một ví dụ không có dòng mới / bình luận:

{ { false && echo "inner true"; } && { echo "inner true" && true; } || { echo "inner false" && false; } || echo "outter false"; }

@Stephane Cảm ơn bạn đã thêm dấu chấm phẩy. Tôi đã sử dụng điện thoại của mình để trả lời vì vậy tôi đã không kiểm tra lại câu trả lời của mình. :)
Livingstaccato

Ý tưởng thú vị. Vâng, tôi đã nghĩ đến việc lồng nhau nếu các câu lệnh nhưng nếu tôi kết nối nhiều thứ với nhau thì nó có thể trở nên lộn xộn.
Mike B

4

Tách từng chuỗi lệnh thành các hàm:

big_block_1() {
  # ...
}
big_block_2() {
  # ...
}
big_block_3() {
  # ...
}

big_block_1 && big_block_2 && big_block_3

0

Tôi luôn muốn viết một hàm "fail" cho phép tôi chỉ định điều tôi sẽ làm khi xảy ra lỗi và sau đó sử dụng ||mẫu. Giống như sau:

function fail() {
  echo "Failure: ${@}"
  exit 1
}

foocommand || fail "couldn't foo"
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.