Trong #! / Bin / bash. Lệnh Unix để có được ngày đầu tiên của một ngày trong tuần trong một tháng


8

Tôi đang tìm kiếm một lệnh Unix thẳng để có được Chủ nhật đầu tiên của tháng tiếp theo, Thứ Hai đầu tiên của tháng tiếp theo, Thứ Ba đầu tiên của tháng tiếp theo, Thứ Tư đầu tiên của tháng tiếp theo, v.v.

  1. Tôi sẽ cần chúng ở định dạng ngày hoàn chỉnh (thời gian không bắt buộc)

  2. Tôi có thể nhận được các số như 2, 3, 4, v.v. Vì tôi không chỉ muốn số, tôi sẽ cần chúng ở định dạng ngày (bao gồm ngày, tháng, năm)

    $ NEXT_MONTH=`date +'%m %Y' -d 'next month'`
    $ echo $NEXT_MONTH
    04 2017
    
    $ NEXT_SUNDAY=`cal $NEXT_MONTH | awk 'NF==7 && !/^Su/{print $1;exit}'`
    $ echo $NEXT_SUNDAY
    2
    
  3. Tôi sẽ cần những ngày này để gửi thông báo cho nhóm email.

Vd: Tôi có thể có được ngày thứ bảy đầu tiên của tháng tiếp theo như dưới đây.

$ firstofmonth=$(date -d '+1 months' '+%Y%m01')
20170401

$ firstsaturday=$(date -d "$firstofmonth" '+%Y-%m')-$((7 - \
                $(date -d "$firstofmonth" '+%u')     ))    
2017-04-1

Câu trả lời:


11

Trong ksh93:

$ printf '%(%F)T\n' 'next month, first Monday'
2017-04-03

bash, vì 4.2 hiện hỗ trợ một buitin %(<format)Tcủa nó printf, nhưng không có khả năng phân tích loại biểu thức ngày này.

Nếu bạn phải sử dụng bashvà muốn sử dụng nó %(<format>)T, bạn vẫn có thể làm điều đó mà không cần phải sử dụng một cái gì đó như:

printf -v code '%(
  t=$((%s + (12 - %-H) * 60 * 60))
  increment=$((8 - %u))
  current_month=%m)T' -1
eval "$code"
until
  t=$((t + increment * 24 * 60 * 60)) # next Monday around mid-day
  printf -v code '%(date=%F month=%m)T' "$t"
  eval "$code"
  [ "$month" != "$current_month" ] # until be get to next month
do
  increment=7 # the first increment is the number of days
              # til Monday. Next increments are just a week.
done
echo "$date"

#! / bin / bash. Tôi đang gặp lỗi dưới đây trong bash $ printf '% (% F) T \ n' 'vào tháng tới, thứ Hai đầu tiên' -bash: printf: `(': ký tự định dạng không hợp lệ
Hima

1
@Hima, tôi đã nói trong ksh93 . bashlà một bản sao chưa hoàn thành của ksh (với một số tính năng của (t) csh và zsh và thậm chí một vài tính năng của riêng nó). Các phiên bản gần đây bashđã thêm hỗ trợ cho printf '%(format)T'từ ksh93, nhưng không có khả năng phân tích loại thông số kỹ thuật ngày này. Thay thế cô ấy bằng #! /path/to/ksh93 -.
Stéphane Chazelas

" bashLà một bản sao chưa hoàn thành của ksh" - Tôi luôn cảm thấy như vậy.
Tim Kennedy

@Stephene, tôi đã thử với lệnh dưới đây để nhận được vào tháng tới vào thứ bảy tuần trước $ cal 04 2017 | awk 'NF <= 7 {in $ 6}' | grep -v "^ $" | đuôi -1 28 Nó hiển thị số 28, nhưng tôi đang tìm ngày hoàn thành 28/11/2017, xin vui lòng nếu có thể với nó.
Hima

9

Giả sử GNU date(cho rằng -dbạn đang sử dụng chính mình) và hệ zshvỏ tương tự cho {1..7}:

$ for i in {1..7} ; do \
    LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
  done | awk '/Mon/ {print $1}'
2017-04-03

Thay thế awk Monbằng bất cứ ngày nào trong tuần là bắt buộc (sử dụng LC_ALL=Cđể lấy tên tháng tiếng Anh bất kể ngôn ngữ của người dùng). Ngoài ra, có thể tốt hơn để lưu trữ điều này thành một biến nếu bạn sẽ truy vấn lại cho mỗi ngày trong tuần:

$ days=$(for i in {1..7} ; do \
           LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
         done)

$ for i in Mon Tue Wed Thu Fri Sat Sun ; do \
    echo "${days}" | awk "/${i}/"'{print $1}' ; \
  done
2017-04-03
2017-04-04
2017-04-05
2017-04-06
2017-04-07
2017-04-01
2017-04-02

Trong bash cũng vậy, mã này trả về tháng tiếp theo Mặt trời, Thứ hai, Thứ tư, Do đó, Thứ sáu, Thứ bảy. Cảm ơn bạn. Tôi nghĩ rằng, tôi có thể sửa đổi lệnh này để có được vào tháng tới vào Chủ nhật, Thứ Hai, Thứ Tư, vv Hãy để tôi thử điều này.
Hima

Xin chào, tôi đã thử lệnh dưới đây để nhận được vào tháng tới vào thứ bảy tuần trước $ cal 04 2017 | awk 'NF <= 7 {in $ 6}' | grep -v "^ $" | đuôi -1 Nó hiển thị số 28, nhưng tôi đang tìm ngày hoàn chỉnh như 28/11/2017, xin vui lòng đề nghị nếu có thể.
Hima

"cho tôi trong {1..7}; làm ngày '+% Y-% m-% d% a' -d" $ (ngày +% Y% m01 -d '2 tháng') $ {i} ngày trước "; xong | awk '/ Sat / {in $ 1}'" - điều này sẽ cung cấp cho 2017-04-29, đó là ngày thứ bảy cuối cùng của tháng tiếp theo. Mã này được chuyển tiếp 2 tháng, đến ngày đầu tiên của tháng đó và sau đó quay lại 1-7 ngày để lấy dữ liệu 7 ngày cuối cùng của tháng trước. Cá nhân tôi sẽ tránh sử dụng cal vì tôi đã thử các ví dụ khác ở đây và không có tác dụng nào trên phiên bản của tôi (CentOS 6).
parkamark

2

PHP thực sự làm cho nó dễ dàng phân tích ngày với đầu vào văn bản, nếu nó có sẵn trên hệ thống của bạn.

Thí dụ:

bash-[522]$ php -qr 'date_default_timezone_set("UTC"); echo date("d-m-Y\n", strtotime("first monday of next month"));'
03-04-2017

Tôi có chức năng này trong .bashrc:

get_date ()
{
    text="$*";
    php -qr "date_default_timezone_set(\"UTC\"); echo date(\"d-m-Y\n\", strtotime(\"$text\"));"
}

Mà tôi có thể sử dụng như:

bash-[523]$ get_date first monday of next month
03-04-2017

Chỉnh sửa Thêm tùy chọn để sử dụngcal

Hầu như mọi hệ thống bashsẽ có cal. Chương trình lịch. Bạn có thể nhận được một danh sách các ngày cho đầu tiên của mỗi ngày trong tuần bằng cách chạy một sự kết hợp của cal, dateawk, như sau:

 cal -hN $(date -d 'next month' +%b' '%Y) | grep -v $(date -d 'next month' +%b) | awk -v date=$(date -d 'next month' +%Y-%m-) '{ printf "%s: "date"%02i\n", $1, $2; }'

Mà sẽ cung cấp cho bạn đầu ra sau đây:

Su: 2017-04-02
Mo: 2017-04-03
Tu: 2017-04-04
We: 2017-04-05
Th: 2017-04-06
Fr: 2017-04-07
Sa: 2017-04-01

Thay đổi $2thành $NFtrong tuyên bố awk để có được ngày xuất hiện cuối cùng của mỗi ngày trong một tháng.


Nó không hoạt động trong bash, $ php -qr 'date_default_timezone_set ("UTC"); ngày echo ("dmY \ n", strtotime ("thứ hai đầu tiên của tháng tiếp theo")); ' -bash: php: lệnh không tìm thấy. xin vui lòng cho tôi biết cách để hoàn thành nó trong bash. và cũng, lệnh để có được vào tháng tới Mặt trời qua Sat. Tôi đã thử nó, một số cách nó ném lỗi. cảm ơn ..!!
Hima

Có nghĩa là bạn chưa phpcài đặt. Tôi đã cập nhật với một ví dụ sử dụng cal, dateawkcác lệnh.
Tim Kennedy

Tôi đã thử lệnh này và ném một lỗi. Cảm ơn bạn.!! $ cal -hN $ (ngày -d 'tháng sau' +% b ''% Y) | grep -v $ (ngày -d 'tháng tới' +% b) | awk -v ngày = $ (ngày -d 'tháng sau' +% Y-% m-) '{printf "% s:" ngày "% 02i \ n", $ 1, $ 2; } 'cal: tùy chọn không hợp lệ - h sử dụng: cal [-13smjyV] [[tháng] năm]
Hima
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.