Hiển thị số của tuần ở định dạng nhất định bằng ncal hoặc cal


15

Không phải bạn chỉ thích nó khi hai lệnh mỗi thứ làm một điều bạn muốn nhưng cả hai đều không làm cả hai?

Đây là những gì calkhông. Định dạng đẹp. Thiếu số tuần mặc dù:

$ cal
    January 2012      
Su Mo Tu We Th Fr Sa  
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
22 23 24 25 26 27 28  
29 30 31              

Đây là những gì ncalkhông. Định dạng kỳ lạ, nhưng với số tuần:

$ ncal -w
    January 2012      
Su  1  8 15 22 29   
Mo  2  9 16 23 30   
Tu  3 10 17 24 31   
We  4 11 18 25      
Th  5 12 19 26      
Fr  6 13 20 27      
Sa  7 14 21 28      
    1  2  3  4  5   

Loại đầu ra tôi muốn, thực sự là một giao thức giữa calncal -w:

$ cal --magik-calendar-week-option
      January 2012      
   Su Mo Tu We Th Fr Sa  
1   1  2  3  4  5  6  7  
2   8  9 10 11 12 13 14  
3  15 16 17 18 19 20 21  
4  22 23 24 25 26 27 28  
5  29 30 31

Câu trả lời:


13

Nếu cả hai lệnh này không phù hợp với nhu cầu của bạn, bạn có thể sử dụng gcalđể làm những gì bạn muốn thay thế.

Thí dụ

$ gcal -K

      April 2014
 Su Mo Tu We Th Fr Sa CW
        1  2  3  4  5 13
  6  7  8  9 10 11 12 14
 13 14 15 16 17 18 19 15
 20 21 22 23 24 25 26 16
 27 28 29 30          17

In số tuần trong cột cuối cùng bên phải.

Người giới thiệu


gcal --starting-day=Monday --with-week-numberphù hợp với nhu cầu của tôi hơn nhưng công cụ này là tuyệt vời.
k0pernikus

9

Điều này nhấn mạnh ngày hôm nay và có thể hiển thị bất kỳ tháng nào qua $1biểu mẫu: YYYY-mm-dd... Nó mặc định cho đến ngày hôm nay

Nó được thiết lập để hiển thị số tuần ISO và ngày đầu tuần là thứ Hai.

#!/bin/bash
# Input reference date is expected in  'YYYY-mm-dd' format
#
today=($(date '+%Y %m %d')); Y=0; m=1; d=2                # establish today's date
[[ -z $1 ]] && ref=(${today[@]}) || ref=(${1//-/ })       # get input date
dNbA=$(date --date="$(date +%Y-%m-01)" +'%u')             # day-number of 1st day of reference month
today[m]=$((10#${today[m]})); ref[m]=$((10#${ref[m]}))    # remove leading zero (octal clash)
today[d]=$((10#${today[d]})); ref[d]=$((10#${ref[d]}))    # remove leading zero (octal clash)
nxtm=$(( ref[m]==12 ?1       :ref[m]+1 ))                 # month-number of next month
nxtY=$(( ref[m]==12 ?ref[Y]+1:ref[Y]   ))                 # year-number of next month
nxtA="$nxtY-$nxtm-1"                                      # date of 1st day of next month
refZ=$(date --date "$(date +$nxtA) yesterday" +%Y-%m-%d)  # date of last day of reference  month
days=$(date --date="$refZ" '+%d')                         # days in reference month

h1="$(date --date="${ref[Y]}-${ref[m]}-${ref[d]}" '+%B %Y')" # header 1 
h2="Mo Tu We Th Fr Sa Su"                                    # header 2 
printf "    %$(((${#h2}-${#h1}-1)/2))s%s\n" " " "$h1"
printf "    %s\n" "$h2"
# print week rows   
printf "%2d  " "$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-01)" +'%V')))" # week-number (of year) with suppressed leading 0
printf "%$(((dNbA-1)*3))s"  # lead spaces (before start of month)
dNbW=$dNbA  # day-number of week
dNbM=1      # day-number of month
while ((dNbM <= days)) ;do
    if (( today[Y]==ref[Y] &&  
          today[m]==ref[m] && 
          today[d]==dNbM )) ;then
        printf "\x1b[7m%2d\x1b[0m " "$dNbM" # highlight today's date 
    else
        printf "%2d " "$dNbM"
    fi
    ((dNbM++))
    if ((dNbW  >=7)) ;then
        cdate=$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-$dNbM)" +'%V'))) # remove leading zero (octal clash)
        printf "\n%2d  " "$cdate" # week-number of year
        dNbW=0
    fi
    ((dNbW++))
done
printf "%$(((8-dNbW)*3))s\n" # trailing spaces (after end of month)

Đây là màn hình của tháng này (có 20tô sáng)

       January 2012
    Mo Tu We Th Fr Sa Su
52                     1 
 1   2  3  4  5  6  7  8 
 2   9 10 11 12 13 14 15 
 3  16 17 18 19 20 21 22 
 4  23 24 25 26 27 28 29 
 5  30 31                

Tôi thậm chí không nhận thấy vấn đề iso. Điều đó sẽ làm :)
k0pernikus

1
@ k0pernikus: Tôi vừa sửa đổi tập lệnh .. (khoảng 35 phút sau khi bạn đăng nhận xét ở trên) .. Nó đã bị bắt kịp 0809được hiểu là bát phân thay vì thập phân .. Bây giờ sẽ ổn thôi ...
Peter.O

7

Bạn có thể sử dụng nlđể đánh số các dòng (đó là mục đích của chương trình :). Nhưng bạn cần trích xuất tuần đầu tiên trong tháng từ một nơi nào đó. Nó có thể được thực hiện từ ncalchính nó:

$ ncal -w 2 2012 | tail -1 | awk '{print $1}'
5

Chúng tôi chèn nltùy chọn này làm tham số cho tùy chọn -v(số dòng bắt đầu) và chỉ cho nó biết các dòng số có số hoặc dấu cách.

$ cal 2 2012 | nl -bp'^[0-9 ]\+$' -w2 -s'  ' -v$(ncal -w 2 2012 | tail -1 | awk '{print $1}')
       February 2012
    Su Mo Tu We Th Fr Sa
 5            1  2  3  4
 6   5  6  7  8  9 10 11
 7  12 13 14 15 16 17 18
 8  19 20 21 22 23 24 25
 9  26 27 28 29

Đây là tất cả mong manh khủng khiếp mặc dù. Dù sao, nếu bạn không cần calcác tùy chọn nâng cao hơn, nó sẽ hoạt động. Bạn có thể đặt nó trong một tập tin và thay thế "$@"nơi tôi đặt 2 2012.


EDIT: Nhưng đây là SAI! Tôi chỉ nhận thấy rằng tuần đầu tiên trong tháng 1 có thể có số 52 hoặc 53! Vì vậy, chúng ta chỉ cần tạo một ngoại lệ cho tháng 1 hoặc chỉ trích xuất tất cả các số trong tuần ncalvà áp dụng chúng cho đầu ra của cal.

Đây là giải pháp tôi nghĩ ban đầu, nhưng tôi nghĩ (một cách sai lầm) tôi sẽ đơn giản hóa nó bằng cách sử dụng nl. Nó sử dụng paste, hợp nhất các tập tin cạnh nhau. Vì không có bất kỳ tập tin nào, chúng tôi phải sử dụng bashism <(...); đó là những gì tôi đã cố gắng tránh

"Tập tin" đầu tiên của chúng tôi sẽ là một danh sách các số trong tuần, với hai dòng trống ở đầu:

$ printf '   \n   \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)


52
 1
 2
 3
 4
 5

Cái thứ hai, chỉ là đầu ra của cal. Tất cả cùng nhau, như là tham số để paste:

$ paste -d' ' <(printf '   \n   \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)) <(cal 1 2011)
        January 2011
    Su Mo Tu We Th Fr Sa
52                     1
 1   2  3  4  5  6  7  8
 2   9 10 11 12 13 14 15
 3  16 17 18 19 20 21 22
 4  23 24 25 26 27 28 29
 5  30 31

Bừa bộn hơn nhiều và không tương thích với nhau. Vây ...


Không quá tuyệt vời: - /. Xem chỉnh sửa của tôi.
angus

7

Tạo chuỗi tuần với ncalvà sử dụng pasteđể có cả hai đầu ra cạnh nhau.

$ paste <(echo; echo; ncal -w | tail -1 | xargs -n1 printf '%2d\n') <(cal)

Nếu bạn không thích có các tab làm dấu phân cách, chỉ cần thêm một cái gì đó như sed 's/\t/ /'


Chỉnh sửa : cách đơn giản hơn, không cần quan tâm đến các tab:

$ paste -d' ' <((echo -n '   '; ncal -w | tail -1 )| fold -w 3) <(cal)

Thanh lịch và là hiện thân của 17 Quy tắc Unix của ESR . Nên là câu trả lời được chấp nhận vì nó thực sự kết hợp đầu ra của calncal(các cách tiếp cận khác sao chép hành vi của một trong hai calhoặc ncal).
giám mục

4

Một cách sử dụng Perl (ngôn ngữ đầu ra của callệnh là tiếng Tây Ban Nha, nhưng tôi hy vọng kết quả không khác với tiếng Anh):

$ cal | perl -pe 'if ( m/\A\s*\d/ ) { s/\A/++$i . qq[ ] x 2/e } else { s/\A/qq[ ] x 3/e }'

Đầu ra:

       enero de 2012   
   lu ma mi ju vi sá do
1                     1
2   2  3  4  5  6  7  8
3   9 10 11 12 13 14 15
4  16 17 18 19 20 21 22
5  23 24 25 26 27 28 29
6  30 31

Giải trình:

-pe                     # For every input line from previous pipe, execute  next
                        # instructions and print to output.
if ( m/\A\s*\d/ )       # If line begins with a digit omitting spaces...
s/\A/++$i . qq[ ] x 2/e # Insert at the beginning of the line a counter plus two spaces.
else                    # else...
s/\A/qq[ ] x 3/e        # Insert three spaces at the beginning of the line.

Làm thế nào điều này sẽ làm việc cho những tháng tiếp theo. Tuần tháng hai không bắt đầu từ ngày 1, họ bắt đầu từ ngày 5/6 tương tự tháng 3 sẽ bắt đầu từ ngày 9/10.
Nikhil Mulley

cal 02 2012, nó sẽ thất bại chứ ??
Nikhil Mulley

@Nikhil: Tôi không hiểu ý của bạn. Bạn có thể cố gắng giải thích nó sâu hơn? Liệu kịch bản thất bại với cal 02 2012? Nó dường như làm việc trong thử nghiệm của tôi.
Birei

@Nikhil: À, ok. Tôi đã hiểu sai câu hỏi. Nó có nghĩa là số tuần tuyệt đối và không liên quan đến mỗi tháng. Tôi sẽ xóa câu trả lời sai của tôi trong một thời gian.
Birei

1
tuyệt vời..không xóa câu trả lời, xin vui lòng giữ nó để tham khảo.
Nikhil Mulley

1

Nếu không có đủ đại diện để nhận xét về câu trả lời bằng slm, gcal có thể được cài đặt trên Mac OS bằng cách sử dụng brew install gcal.

(Tôi đã tìm thấy câu trả lời ở đây trước, sau đó câu trả lời này sẽ hỏi khác, nhưng câu trả lời unix thiếu tất cả thông tin tôi cần để cài đặt trên máy mac.)


0

Đây là giải pháp của tôi ngắn hơn về mã và hoạt động tốt cho các ngày khác so với tháng hiện tại. Xin lỗi cho người dân Hoa Kỳ, điều này sử dụng định dạng ISO, tức là ngày đầu tuần là thứ hai. Điều này được thực hiện với tùy chọn -m cho cal và tùy chọn% V cho ngày

#!/bin/bash
if [ "$1" = "" ]
then
  when="now"
else
  when="$1"
fi
y=$(date --date "$when" +%Y )
if [ $? -ne 0 ]
then
  exit
fi
m=$(date --date "$when" +%m )
w=$(date --date $(printf %4d%02d01 $y $m) +%V)
cal -m $m $y |
  awk -v w=$w '
    NR>2{ww=w++}
    $0!=""{printf "%2s %s\n", ww , $0}
  '

0

Tôi đã thực hiện kịch bản này để tạo lịch làm nhiệm vụ cho các đội. Nó tạo ra lịch với số tuần và gán tên cho chúng (chỉ đơn giản là quay vòng). Sau khi đầu ra được in, bạn chỉ cần sao chép nó vào excel và thực hiện "text to cột" bằng cách; và một lần nữa thực hiện "text to cột" trên cột đầu tiên bằng cách sử dụng tùy chọn "fixed". Lợi ích của lịch này (so sánh với hướng ngang) là bạn có thể sử dụng bộ lọc tự động (Alt + dff) và chỉ tìm thấy các tuần của bạn.

#! / usr / bin / ksh
y = 2017
set -A team1 Petars Justas Richard Jukka Jesper
set -A team2 Modestas Timo Mats Andreas

i1 = 0
i2 = 0
wn = 1
riêng = 1

tiếng vang "Tháng WN Mo Tu We Th Fr Sa Su; Team1; Team2"
ycal = `cho m trong 1 2 3 4 5 6 7 8 9 10 11 12
làm
IFS =
        cal -m $ m $ y | egrep -v "Mo | ^ $" | trong khi đọc dòng
        làm
                echo $ line | grep -q $ y && mname = $ line || in $ mname $ line | sed 's /' $ y '//'
        làm xong
xong rồi
IFS =
echo "$ ycal" | trong khi đọc dòng2
làm
IFS =
        tiếng vang "$ line2" | grep -v "1 2 3 4 5 6 7" | egrep -q "* 1 | * 1 $" || hãy để wn ++
        [$ own -ne $ wn] && {\
                [$ i1 -eq $ {# team1 [@]} - 1] && i1 = 0 || hãy để i1 ++; \
                [$ i2 -eq $ {# team2 [@]} - 1] && i2 = 0 || hãy để i2 ++; }
        printf '% 2s% s;% s;% s \ n' $ wn $ line2 $ {team1 [$ i1]} $ {team2 [$ i2]}
        riêng = $ wn
làm xong

Xin lỗi, mã hơi khó chịu ... và không có nhận xét ... nhưng nó hoạt động tốt;)


0

Tôi thực sự không muốn cài đặt gcalvà tôi không thể làm cho nó hoạt động đúng trên hệ thống của mình. Vì vậy, không có gcal, câu trả lời của funollet thực sự là giải pháp tốt nhất. Tôi chỉ thay đổi nó một chút để nó cũng giữ nguyên định dạng như sáng ngày , màu sắc , v.v. bằng cách sử dụng lệnh. Tôi cũng loại bỏ các ký tự thừa, làm cho nó phù hợp như một bí danh, như sau:script

alias today="paste -d' ' <((echo ' '{,};ncal -w|tail -1)|fold -w3) <(script /dev/null -qc cal)"

Hoặc thay thế cal bằng một chức năng mới. Tuy nhiên, với điều này bạn không thể làm những việc như thế cal -3. Bạn nhận được đúng tuần nhưng chúng không được căn chỉnh chính xác. Một giải pháp đơn giản nhưng không đầy đủ là kiểm tra nếu calđược gọi mà không có đối số, như vậy:

function cal {
    if [[ $# -eq 0 ]]; then
        paste -d' ' <((echo ' '{,};ncal -w $@|tail -1)|fold -w3) <(script /dev/null -qc "cal $@")
    else
        /usr/bin/cal "$@"
    fi
}
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.