When I try "cal | tail -6" in my unix machine, I get -
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
but when I try "cal | tail -6 | awk '{print $7}'", I get -
10
17
24
where is 3 going ? My requirement is basically all weekdays i.e column 2,3,4,5 & 6.
But I'm getting wrong output because of the strange behavior of "cal"
There are only 3 whitespace delimited columns in your first row. cal is working exactly as corrected, you are not understanding how awk works. As far as awk is concerned there is no 7th column in your first row as it yields attention to whitespace delimited columns, not fixed width columns.
A quick google search reveals you can use
BEGIN { FIELDWIDTHS = "3 3 3 3 3 3 3" }
In your awk script.
Since all of your columns in each row are three characters wide, you could use this to extract the days you wish for. For example, if you wanted only the 7th day in a column, you could do the following:
cal | sed 's/^\(.\{18\}\).*$/\1/'
This command would remove the first 18 characters in the line, which are the entries for the first 6 days of the week.
To extract a particular day, such as the fourth day, you could do this:
cal | sed 's/^.\{9\}\(.\{3\}\).*$/\1/'
To remove the first day of the week and the last day, you could do this:
cal | sed -e 's/^.\{3\}//' -e 's/^\(.\{15\}\).\{3\}$/\1/'
May be a row-wise extraction will do the trick. Try ncal. For example:
$ ncal
November 2012
Mo 5 12 19 26
Tu 6 13 20 27
We 7 14 21 28
Th 1 8 15 22 29
Fr 2 9 16 23 30
Sa 3 10 17 24
Su 4 11 18 25
or fill the absent dates with place holder (with '-' for example):
kent$ cal -s|tail -6|awk 'NR==1&&NF<7{gsub(/^ */,"");for(i=1;i<=(7-NF);i++) x=" - "x;$0=x" "$0;}1'
- - - - 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
then you could get the column, replace '-' with " " if needed. e.g. for $7:
kent$ cal -s|tail -6|awk 'NR==1&&NF<7{gsub(/^ */,"");for(i=1;i<=(7-NF);i++) x=" - "x;$0=x" "$0;}{print $7}'
3
10
17
24
Note that todays date is highlighted unless you turn it off (-h). Use cut to extract the wanted columns:
cal -h | cut -c19-20
Output:
Sa
3
10
17
24
Related
I need that the output of the command cal stay highlighted in a variable in order print it into a wallpaper so I can disable the calendar software to save resources of a low spec computer. How can I make the cal output stay highlighted?
Perhaps something like:
cal -h | sed 's/ \('"$(date +%_d)"'\) /{\1}/'
outputs
June 2021
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
I'm pretty new to bash and all the terminal in general - I've been messing around with cal and the date scripts wondering if there is anyway to list all the dates of monday of the current month .
My thought process is going thru the cal command, listing out the dates and maybe cutting a column from that input. Is that possible ?
You can do it with date command. Print 10 mondays since month ago:
for x in $(seq 0 9)
do
date -d "$x monday 5 week ago"
done
And grep only current month. Full command: for x in $(seq 0 9); do; date -d "$x monday 5 week ago"; done | grep $(date +%b)
Output:
Mon Jun 5 00:00:00 MSK 2017
Mon Jun 12 00:00:00 MSK 2017
Mon Jun 19 00:00:00 MSK 2017
Mon Jun 26 00:00:00 MSK 2017
Given:
$ cal
June 2017
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
You can do:
$ cal | awk 'NF>5{print $2}'
Mo
5
12
19
26
If you want something that will support any day of cal, use the field width (gawk only this):
$ cal | gawk -v n=5 '
BEGIN{
FIELDWIDTHS = "3 3 3 3 3 3 3"
}
FNR>1{print $n}'
Th
1
8
15
22
29
Or, as pointed out in comments:
$ ncal | awk '/^Mo/'
Mo 5 12 19 26
Combination of cal,cut commands to achieve the output.
cal -h| cut -c'4,5'
Remove the highlight and cut the characters which suits in the fields of monday.
ncal | sed -n '/^Mo/p'
The output as below:
Mo 5 12 19 26
How can I use brace-expansion to make the equivalent of cal 8 2014; cal 9 2014? cal {8,9} 2014 expands to cal 8 9 2014 (showing the 9th of September.) cal {08 2014,09 2014} isn't a valid brace expansion, and I can't use cal {"08 2014","09 2014"} because that expands to cal "08 2014" "09 2014" which is two parameters that obviously don't make sense together here :/ I'm starting to question the utility of brace expansion....
brace-expansion is great, for loops are also great, but add printf|sh to your repertoire and
you'll be in great shape:
printf "cal %s 2014\n" {8,9}|sh
One clear benefit is you can run it without |sh first to see if it looks right.
You could also escape spaces so that the brace-expansion includes cal and 2014:
$ echo cal\ {8,9}\ 2014\;
cal 8 2014; cal 9 2014;
And then pipe through sh:
$ echo cal\ {8,9}\ 2014\;|sh
August 2014
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
September 2014
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
Problem statement is
If todays date is single digit,then replace that date with single *
if the today date is double digit,then replace it with double *
my code works for single digit date.
but my sed code is unable to substitute double digit with double **.
Here is my code:
#!/bin/sh
set `date`
if [ $3 -le 9 ]
then
n=`cal | tail -n +3 | grep -n "$3"| cut -d ":" -f1 | head -n 1`
n=`expr $n + 2`
cal | sed "$n s/$3/*/"
else
cal | sed "s/$3/**/"
fi
whats the error in this line
cal | sed "s/$3/**/"
assume $3 contains value 19.
here's the output of cal | cat -vte
abhijith#abhijith-compaq-420:~/Desktop$ cal | cat -vte
December 2013 $
Su Mo Tu We Th Fr Sa $
1 2 3 4 5 6 7 $
8 9 10 _^H1_^H1 12 13 14 $
15 16 17 18 19 20 21 $
22 23 24 25 26 27 28 $
29 30 31 $
$
cal | sed "s/$3/**/" works fine for me. But I recommend to rewrite your script this way:
#!/bin/sh
day=`date +%d`
case $day in
?) cal | sed "s/ $day/ */" ;;
??) cal | sed "s/$day/**/" ;;
esac
UPDATE
Since you say it's not working for you, let's get back to the basics. What will be the output of this script:
#!/bin/sh
day=9; cal | sed "s/ $day/ */"
day=19; cal | sed "s/$day/**/"
I get:
December 2013
S M Tu W Th F S
1 2 3 4 5 6 7
8 * 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
December 2013
S M Tu W Th F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 ** 20 21
22 23 24 25 26 27 28
29 30 31
Script for counting weekends (saturdays AND sundays) in a given month, by passing in month and year. How to write it?
New in scripting, can't find solution to this easy task.
You want to count weekends Sat and Sun, So I am guessing you mean 2 day weekends.
Hope this helps. VonBell
In unix/linux you can easily parse the cal command for the given month.
$ cal 04 2013
April 2013
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
The numerical date always start on Line 3, the cols for each day are constant
When I used the commands below to extract the weekend (sun, Sat)
As you can see Sun is cols 1,2,3 (with space included) and Sat is cols 19,20
$ cal 04 2013|tail +3|cut -c1-3,19,20
.. 6
7 13
14 20
21 27
28
When I execute the script below as cntWkEnd.sh The output is as follows
1 equals one day wkend and 2 equals 2 day wkend sat and sun
$ ./cntWkEnd.sh 04 2013
1
2
2
2
1
0
To count only 2 day weekends you can add at the command line or in the script
the following
./cntWkEnd.sh 04 2013|grep "2"|wc -l (Output of 3 shown below)
3
This the contents of cntWkEnd.sh
#!/bin/bash
cal $1 $2|tail +3|cut -c1-3,19,20 |\
while read WkEnd
do
echo $WkEnd|wc -w
done