Ngày đầu ra hiện tại sử dụng cal


7

Tôi được yêu cầu xuất ra ngày hiện tại bằng cách sử dụng callệnh.

Cho đến nay, tôi phát hiện ra rằng trước ngày hiện tại có một _biểu tượng. Tôi quyết định sử dụng grepở đây : cal | grep '\b_*', nhưng nó cho ra cả tuần. Tôi đã thử một vài biến thể, nhưng nó không thành công.

Thật ra, cũng có một trường hợp, khi ngày hiện tại chỉ có một chữ số, nên dường như tôi phải sử dụng tr -d ' 'ở đây.

Tôi không có ý tưởng làm thế nào để kết hợp tất cả các lệnh này với nhau.

Câu trả lời:


8

Khi đầu ra của callệnh không phải là thiết bị đầu cuối, nó sẽ áp dụng gạch chân của người nghèo vào số ngày cho ngày hôm nay, bao gồm đặt dấu gạch dưới và ký tự lùi trước mỗi ký tự để gạch chân. Bạn có thể thấy điều đó bằng cách hiển thị các ký tự một cách trực quan ( ^Hcó nghĩa là control-H , là ký tự backspace):

cal | cat -A
cal | cat -vet

hoặc bằng cách nhìn vào một bãi chứa hex:

cal | hd
cal | od -t x1

Vì vậy, những gì bạn cần là phát hiện các ký tự được gạch chân và xuất chúng.

Với GNU grep, có một cách dễ dàng để in tất cả các kết quả khớp của biểu thức chính quy: sử dụng -otùy chọn. Một nhân vật gạch dưới được kết hợp bởi các biểu thức chính quy mở rộng _^H.nơi ^Hlà một nhân vật xóa lùi theo nghĩa đen, không phải là hai nhân vật ^H, và .là nhân vật để in. Thay vì gõ ký tự backspace, bạn có thể dựa vào thực tế rằng đây là cách duy nhất cal sử dụng dấu gạch dưới trong đầu ra của nó. Vậy là đủ để phát hiện các dấu gạch dưới và để lại các khoảng trống dưới dạng các ký tự chưa từng có.

cal | grep -o '_..'

Chúng tôi đang đóng, nhưng đầu ra chứa chuỗi dấu gạch dưới gạch dưới và các chữ số nằm trên các dòng riêng biệt. Bạn có thể loại bỏ tất cả các ký tự không có chữ số (và thêm lại một dòng mới):

cal | grep -o '_..' | tr -d 0-9; echo

Ngoài ra, bạn có thể lặp lại mẫu _..để khớp với nhiều chữ số được gạch chân. Điều này để lại phần gạch chân trong đầu ra, bạn có thể sử dụng tr hoặc sed để loại bỏ nó.

cal | grep -E -o '(_..)*'
cal | grep -E -o '(_..)*' | tr -d '\b_'
cal | grep -E -o '(_..)*' | sed 's/_.//g'

Bạn có thể làm điều này với sed, nhưng nó không hoàn toàn đơn giản. Sed cung cấp một cách dễ dàng để chỉ in các dòng khớp (sử dụng -ntùy chọn để chỉ nhận các dòng được in rõ ràng), nhưng không có cách trực tiếp để in nhiều lần xuất hiện của một trận đấu trên một dòng. Một cách để giải quyết điều này là tận dụng thực tế là có nhiều nhất hai ký tự được gạch chân và có một slệnh để chuyển đổi và xuất các dòng chứa một ký tự được gạch chân và một ký tự khác cho hai dòng. Như trước đây, tôi sẽ không khớp với các không gian rõ ràng.

cal | sed -n 's/.*_.\(.\)_.\(.\).*/\1\2/p; s/.*_.\(.\).*/\1/p'

Một cách tiếp cận khác với sed, giả sử rằng chỉ có một phân đoạn được gạch chân trên một dòng, là loại bỏ mọi thứ trước nó và mọi thứ sau nó.

cal | sed -n 's/^[^_]*_/_/; s/\(_..\)[^_]*$/\1/p'

Điều này để lại các dấu gạch dưới; chúng ta có thể loại bỏ chúng với sự thay thế thứ ba.

cal | sed -n 's/^[^_]*_/_/; s/\(_..\)[^_]*$/\1/; s/_.//gp'

11

Cách thích hợp để làm điều này chỉ là sử dụng date:

% date +%d
19

Dấu gạch dưới bạn nhìn thấy không phải là dấu gạch dưới, mà là ký tự điều khiển được hiển thị bởi thiết bị đầu cuối của bạn. Nếu bạn thực sự muốn sử dụng cal, bạn cần tìm hiểu nhân vật điều khiển đó là gì và tìm kiếm nó. Bạn có thể sử dụng điều này bằng cách sử dụng một cái gì đó như cal | xxd.

Một vấn đề khác là calchỉ xuất ra ký tự điều khiển này khi thiết bị xuất chuẩn là một tty, vì vậy bạn cần phải thuyết phục rằng nó là một (xem xét scriptcho điều này).


Khi nó không phải là một thiết bị đầu cuối, những gì bạn nhận được một dấu gạch dưới, cộng với ký tự điều khiển cũ nhất trong sách: backspace. Nó tạo ra một "19" được gạch chân dưới dạng dấu gạch dưới gạch dưới 1 dấu gạch dưới dấu gạch dưới 9.
hobbs

1
@hobbs Tôi không nhận được điều đó trên produc-linux 2.29.1 - không có gì là đầu ra dưới ngày hiện tại khi không được kết nối với TTY.
Chris Xuống

3

Hiện tại tôi không có lệnh GNU cal, nhưng điều này gần với những gì bạn muốn:

cal | grep -Eo '_[[:digit:]]+' | sed 's/_//'

Grep -Enói để cho phép các biểu thức chính quy mở rộng (đối với lớp [[: chữ số:]]); các -olá cờ nói để chỉ ra các phần gắn kết; lệnh sed loại bỏ dấu gạch dưới.

Đó là cách cal + grep để làm điều đó, nhưng như Chris nói , cách thông thường để có được ngày hiện tại là bằng datelệnh.


Không hoàn toàn: có một khoảng lùi giữa dấu gạch dưới và chữ số.
Gilles 'SO- ngừng trở nên xấu xa'

-1
cal | cat -vet | grep -o "H....." | cut -c 2,6

Đơn giản và hoạt động tốt, mặc dù đó không phải là cách tốt nhất.


Đồng nghĩa với việc "thêm định dạng và đặt câu", nhưng bấm nhầm; lời xin lỗi của tôi cho bản tóm tắt chỉnh sửa
Jeff Schaller
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.