nếu điều kiện trên nhiều dòng trong bash shell


19

Tôi có một hàm bash shell lấy một đối số và thực hiện một cái gì đó trên nó nếu cần.

do_somthing() {
  if [need to do something on $1]
  then
    do it
    return 0
  else
    return 1
  fi
}

Tôi muốn gọi phương thức này với một vài đối số và kiểm tra xem ít nhất một trong số chúng có thành công hay không.

Tôi đã thử một cái gì đó như:

if [ do_something "arg1" ||
     do_something "arg2" ||
     do_something "arg3" ]
then
  echo "OK"
else
  echo "NOT OK"
fi

Điều gì sẽ là cú pháp chính xác cho điều đó?
EDIT
Ngoài ra - Tôi muốn đảm bảo rằng ngay cả khi điều kiện đầu tiên là đúng, tất cả các điều kiện khác vẫn sẽ được đánh giá.

Cảm ơn,


Tôi đã cập nhật câu trả lời của mình.
kiến tạo

Cảm ơn, bạn có thể vui lòng cung cấp một ví dụ?
Itay

1
Tôi đã thêm một ví dụ mã vào câu trả lời của tôi.
kiến tạo

Câu trả lời:


7

Chạy các lệnh trước, sau đó kiểm tra xem ít nhất một trong số chúng có thành công hay không.

#!/bin/bash

success=0
do_something arg1 && success=1
do_something arg2 && success=1
do_something arg3 && success=1

if ((success)); then
    printf 'Success! At least one of the three commands succeeded\n'
fi

3
Điều này thật khó hiểu, tôi sẽ rất vui nếu bạn có thể cung cấp một số lời giải thích về cách các câu lệnh có điều kiện hoạt động trong bash ..., do_s Something trả về 0 khi thành công, nhưng sau đó chúng tôi cập nhật thành công lên 1 ..., if ((success))đánh giá thành một cái gì đó khác với if success. Tôi bối rối :)
Itay

2
@Itay ((...))là một lệnh số học. Nếu kết quả bên trong, khác không, nó trả về giá trị đúng (0). Nếu kết quả bên trong là 0, nó trả về false (1). "Thành công" được coi là một biến mà nó dự kiến ​​sẽ chứa một số. Xem mywiki.wooledge.org/ArithmeticExpression
geirha

Cảm ơn, tôi đoán rằng phần làm tôi bối rối là 0 là đúng và 1 là sai thường là ngược lại :)
Itay

2
@Itay Vâng, lúc đầu có thể khó hiểu. Bash khác với các ngôn ngữ có mục đích chung ở chỗ nó là "dựa trên lệnh"; nó không gọi các hàm, nó không có các lớp và phương thức, nó chạy các lệnh và kiểm tra các trạng thái thoát của lệnh. Và việc chạy các lệnh trong bash sẽ dễ dàng hơn nhiều so với các ngôn ngữ như C, python, java, perl, v.v. Lệnh thoát với 0 để báo hiệu thành công và 1-255 cho các loại lỗi khác nhau. (Một lệnh thường chỉ có thể thành công theo một cách, nhưng thất bại vì nhiều lý do khác nhau)
geirha

2
Giải pháp này có ưu điểm là bạn có thể nhận xét các dòng bạn không muốn tắt chúng tạm thời
Josiah Yoder

31

Sử dụng dấu gạch chéo ngược.

if [ $(do_something "arg1") ] || \
   [ $(do_something "arg2") ] || \
   [ $(do_something "arg3") ]
then
  echo "OK"
else
  echo "NOT OK"
fi

CHỈNH SỬA

Ngoài ra - Tôi muốn đảm bảo rằng ngay cả khi điều kiện đầu tiên là đúng, tất cả các điều kiện khác vẫn sẽ được đánh giá.

Điều đó là không thể chỉ trong một câu lệnh if. Thay vào đó, bạn có thể sử dụng một vòng lặp for lặp lại các đối số và đánh giá chúng một cách riêng biệt. Cái gì đó như:

do_something() {
  for x in "$@"
  do
    if [need to do something on $x]
    then
      do it
    else
      echo "no action required on $x"
    fi
  done
}

cảm ơn, đã thử nó - tôi gặp lỗi[: do_something: unary operator expected
Itay 11/05/13 lúc

Bạn đã đặt từng đánh giá giữa các dấu ngoặc riêng của nó? Vì vậy, [ expr1 ] || [ expr2 ]thay vì [ expr1 || expr2 ].
kiến tạo

vâng, tôi đã làm: (...
Itay

Tôi đoán là do_something "arg1"được hiểu là hai đối số trong khi biểu thức nên là unary. Bất kỳ cách làm do_something "arg1"được đánh giá là một đối số?
Itay

1
Bạn đúng. Điều này cũng hoạt động : if [ $(do_something "arg1") ].
kiến tạo

5

Cú pháp đúng là:

if  do_something "arg1" || \
    do_something "arg2" || \
    do_something "arg3"
then
  echo "OK"
else
  echo "NOT OK"
fi

\ được sử dụng để báo cho shell một lệnh tiếp tục trong dòng tiếp theo.

EDIT : Tôi nghĩ rằng điều này nên làm những gì bạn muốn:

#!/bin/bash

do_something() {
  if [need to do something on $1]
  then
    do it
    echo "OK"
  else
    echo "NOT OK"
  fi
}

do_something "arg1"
do_something "arg2"
do_something "arg3"

Cảm ơn, kết quả có lỗi:[: too many arguments
Itay 11/05/13

@ Trả lời cập nhật.
Eric Carvalho

Cập nhật câu hỏi - đây chưa phải là câu trả lời cuối cùng :(
Itay 11/05/13

-1

Tôi thích:

if {
    do_something "arg1" ||
    do_something "arg2" ||
    do_something "arg3"
}; then
    echo "OK"
else
    echo "NOT OK"
fi

Kịch bản của bạn hoàn toàn không hoạt động: sau tham số thử nghiệm đầu tiên, nó sẽ tạo ra một \nký tự, vì vậy ifcâu lệnh của bạn sẽ tạo ra một số lỗi và do_somethingkhông phải là tên lệnh, vì vậy sẽ có nhiều lỗi hơn
damadam
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.