Jasdeep Singh
Jasdeep Singh

Reputation: 3326

using awk to do exact match in a file

i'm just wondering how can we use awk to do exact matches.

for eg

$ cal 09 09 2009
   September 2009
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



$ cal 09 09 2009 | awk '{day="9"; col=index($0,day); print col }'
17
0
0
11
20
0
8
0

As you can see the above command outputs the index number of all the lines that contain the string/number "9", is there a way to make awk output index number in only the 4th line of cal output above.??? may be an even more elegant solution?

I'm using awk to get the day name using the cal command. here's the whole line of code:

     $ dayOfWeek=$(cal $day $month $year | awk '{day='$day'; split("Sunday Monday Tuesday Wednesday Thursday Friday Saturday", array); column=index($o,day); dow=int((column+2)/3); print array[dow]}')

The problem with the above code is that if multiple matches are found then i get multiple results, whereas i want it to output only one result.

Thanks!

Upvotes: 2

Views: 1123

Answers (4)

SiegeX
SiegeX

Reputation: 140237

Limit the call to index() to only those lines which have your "day" surrounded by spaces:

awk -v day=$day 'BEGIN{split("Sunday Monday Tuesday Wednesday Thursday Friday Saturday", array)} $0 ~ "\\<"day"\\>"{for(i=1;i<=NF;i++)if($i == day){print array[i]}}'

Proof of Concept

$ cal 02 1956
    February 1956
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


$ day=18; cal 02 1956 | awk -v day=$day 'BEGIN{split("Sunday Monday Tuesday Wednesday Thursday Friday Saturday", array)} $0 ~ "\\<"day"\\>"{for(i=1;i<=NF;i++)if($i == day){print array[i]}}'
Saturday

Update

If all you are looking for is to get the day of the week from a certain date, you should really be using the date command like so:

$ day=9;month=9;year=2009; 
$ dayOfWeek=$(date +%A -d "$day/$month/$year")
$ echo $dayOfWeek
Wednesday

Upvotes: 4

glenn jackman
glenn jackman

Reputation: 246754

This is so much easier to do in a language that has time functionality built-in. Tcl is great for that, but many other languages are too:

$ echo 'puts [clock format [clock scan 9/9/2009] -format %a]' | tclsh
Wed

Upvotes: 1

William Pursell
William Pursell

Reputation: 212208

If you want awk to only output for line 4, restrict the rule to line 4:

$ awk 'NR == 4 { ... }'

Upvotes: 0

shellter
shellter

Reputation: 37258

you wrote

cal 09 09 2009

I'm not aware of a version of cal that accepts day of month as an input, only

 cal ${mon} (optional) ${year} (optional)

But, that doesn't affect your main issue.

you wrote

is there a way to make awk output index number in only the 4th line of cal output above.?

NR (Num Rec) is your friend and there are numerous ways to use it.

cal 09 09 2009 | awk 'NR==4{day="9"; col=index($0,day); print col }' 

OR

cal 09 09 2009 | awk '{day="9"; if (NR==4) {col=index($0,day); print col } }' 

ALSO

In awk, if you have variable assignments that should be used throughout your whole program, then it is better to use the BEGIN section so that the assignment is only performed once. Not a big deal in you example, but why set bad habits ;-)?

HENCE

cal 09 2009 | awk 'BEGIN{day="9"}; NR==4 {col=index($0,day); print col }'

FINALLY It is not completely clear what problem you are trying to solve. Are you sure you always want to grab line 4? If not, then how do you propose to solve that?

Problems stated as " 1. I am trying to do X. 2. Here is my input. 3. Here is my output. 4. Here is the code that generated that output" are much easier to respond to.

It looks like you're trying to do date calculations. You can be much more robust and general solutions by using the gnu date command. I have seen numerous useful discussions of this tagged as bash, shell, (date?).

I hope this helps.

Upvotes: 2

Related Questions