Làm cách nào để sử dụng truy vấn If-Else dựa trên ngày trong tuần?


10

Vấn đề: Tôi cần kiểm tra xem hôm nay có phải là thứ Năm không và thực hiện các hành động khác nhau dựa trên kết quả của tình trạng này. Tôi đã thử hai cách tiếp cận khác nhau:

Lấy tên ngày:

DAYOFWEEK=$(date +"%a")
echo DAYOFWEEK: $DAYOFWEEK
if ["$DAYOFWEEK" == "Thu"]; 
then   
   echo YES
else
    echo NO
fi

Lấy số ngày:

DAYOFWEEK=$(date +"%u")
echo DAYOFWEEK: $DAYOFWEEK

if ["$DAYOFWEEK" == 4]; 
then
   echo YES
else
   echo NO
fi

Trong cả hai trường hợp, đầu ra là KHÔNG, mặc dù nó phải là CÓ. Chuyện gì thế?


1
Một lưu ý phụ: những thứ đó ;sẽ được yêu cầu nếu bạn có thencùng dòng với if. Trong trường hợp này, chúng là dư thừa.
manatwork

Câu trả lời:


12

Vấn đề là thiếu trống.

Đoạn mã sau sẽ hoạt động trong các shell mà [lệnh dựng sẵn chấp nhận ==làm bí danh cho =:

if [ "$DAYOFWEEK" == 4 ];  then    echo YES; else    echo NO; fi

Nhưng hãy ghi nhớ (xem help testtrong bash):

  • ==không được đề cập chính thức, bạn nên sử dụng =để so sánh chuỗi
  • -eqđược dành cho các bài kiểm tra số học thập phân (sẽ không tạo ra sự khác biệt ở đây date +%unhưng date +%dchẳng hạn như khi so sánh 04và so sánh 4về số lượng nhưng khác nhau về mặt từ vựng).

Tôi thích:

 if [ "${DAYOFWEEK}" -eq 4 ];  then    echo YES; else    echo NO; fi

Nói chung, bạn nên thích cách tiếp cận số ngày , bởi vì nó có ít phụ thuộc hơn vào miền địa phương hiện tại . Trên hệ thống của tôi, đầu ra của date +"%a"ngày hôm nay Do.


3

Đừng bỏ qua caseđó thường là cách tốt hơn để làm những việc này:

Cũng cần lưu ý rằng đầu ra của date +%aphụ thuộc vào miền địa phương, vì vậy nếu bạn mong đợi tên tiếng Anh, tập lệnh của bạn sẽ ngừng hoạt động khi được người dùng Pháp hoặc Hàn Quốc gọi.

case $(LC_ALL=C date +%a) in
   (Mon) echo first day of the week;;
   (Thu) do-something;;
   (Sat|Sun) echo week-end;;
   (*) echo any other day;; # last ;; not necessary but doesn't harm
esac

Lưu ý rằng ở trên là một trong những trường hợp hiếm hoi $(...)không cần trích dẫn (mặc dù trích dẫn sẽ không gây hại. Giống như trong var="$(...)").


0

Trong cùng một ý tưởng, tôi sử dụng đoạn mã sau để "vô hiệu hóa" một cron trước một giờ đã chọn
Tất nhiên, tôi muốn thay đổi chính crontab ... nếu tôi được cấp các quyền cần thiết để :)

Đây là một thử nghiệm đơn giản trong đó hủy bỏ tập lệnh bash trừ khi chúng ta vào ban đêm.

# Delay or restrict execution.
# Here, we quit unless hour is greater than (gt) 2 and (-a) lower than (lt) 7
# i.e. execution happens only at 3,4,5&6 o'clock.
if  /usr/bin/test `date '+%H'` -gt 2 -a `date '+%H'` -lt 7; then
  echo LETS_START_PROCESSING;
else
  exit;
fi

#Put job here

Tại sao sử dụng /usr/bin/testthay vì [lệnh dựng sẵn của shell ?
Stéphane Chazelas

@ Stéphane Chazelas Tôi đã không sử dụng 3,4,5,6 vì tôi không có quyền truy cập vào crontab. ( đây là dòng thứ 2 trong bài đăng của tôi :) Các máy chủ của chúng tôi được quản lý bởi Claranet và chúng tôi đã mất một tuần vé-ping-pong để có được ... một cron hoạt động (không đùa). Vì vậy, chúng tôi tránh làm rối và mở lại vé khi có thể :) Vì lý do đó, chúng tôi đã yêu cầu một nhiệm vụ cron hàng giờ thay vì hàng ngày và cho đến khi tất cả các thử nghiệm của chúng tôi được thực hiện, sẽ không dễ dàng chạm vào nhiệm vụ hơn, và thêm các điều khiển của chúng tôi trong kịch bản thực hiện.
Balmipour

À, xin lỗi, tôi nghĩ bạn có nghĩa là bạn không có quyền sửa đổi crontệp thực thi trái ngược với crontab của người dùng.
Stéphane Chazelas

@ Stéphane Chazelas Về cú pháp kiểm tra, tôi thích nó hơn [] hoặc [[]] vì tôi đã thử tập lệnh của mình trên một số máy chủ khác trước, nơi tôi có thể sử dụng crontab. Sau quá nhiều bất ngờ với dơi, tôi có thói quen sử dụng đường dẫn tuyệt đối trong crontabs càng nhiều càng tốt. Người ta có thể nói rằng nó làm cho các bài kiểm tra trở nên xấu xí, và sẽ đúng ... nhưng tôi sẽ trả lời rằng bài kiểm tra vỏ luôn luôn xấu xí, và cũng sẽ đúng ^^ Điều quan trọng với tôi là có câu trả lời phù hợp với sao chép / dán đơn giản, và bao gồm một số giải thích.
Balmipour

1
Lưu ý rằng -akhông được chấp nhận trong test. Theo tiêu chuẩn, bạn sẽ sử dụng: hour=$(date +%H); if [ "$hour" -gt 2 ] && [ "$hour" -lt 7 ](hoặc hour=`date +%H`nếu bạn cần tương thích với vỏ Bourne, đó là Solaris 10 trở lên và có thể là một số đơn vị SCO hiếm hoi hiện nay)
Stéphane Chazelas

0

Để dừng tập lệnh trong ngày trong tuần, chỉ xóa dòng trong ngày:

DAYOFWEEK=$(date +"%u")
echo "$DAYOFWEEK";
if [ "$DAYOFWEEK" == 1 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 2 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 3 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 4 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 5 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 6 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 7 ]; then exit; else echo; fi

Chào mừng bạn đến với Unix SE! Tôi không chắc chắn nếu tôi hiểu chính xác dòng đầu tiên của bạn. Sẽ không if [ "$DAYOFWEEK" -lt 7 ]tốt hơn sao?
peterh - Phục hồi Monica

-1

Trước tiên, bạn nên trích dẫn bài tập DAYOFWEEK = "$ (ngày +% u)"

Và bạn cần có khoảng trắng ở mỗi bên của dấu ngoặc [và].

Dấu chấm phẩy ở cuối dòng là dư thừa.


1
Việc trích dẫn là không cần thiết.
H.-Dirk Schmitt

Để mở rộng nhận xét của @ H.-DirkSchmitt: lý do tại sao trích dẫn không cần thiết là đầu ra sẽ không chứa bất kỳ khoảng trắng nào.
một CVn

@ MichaelKjorling: Không - không bao giờ cần thiết ;-) Hãy thử ví dụ:a=$(echo 1 2 3); echo $a;
H.-Dirk Schmitt

@ H.-DirkSchmitt a=$(echo "1 2 3"); echo $acó nhiều khoảng trắng giữa các chữ số (StackExchange sẽ không cho phép tôi biến nó thành một bản sao và dán đơn giản, thật không may).
một CVn

@ MichaelKjorling - xem man bash "Nếu thay thế xuất hiện trong dấu ngoặc kép, việc tách từ và mở rộng tên đường dẫn không được thực hiện trên kết quả." Vì vậy, nó làm cho trong trường hợp câu hỏi và ví dụ "1 2 3" không có sự khác biệt.
H.-Dirk Schmitt
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.