-5

I have a text file with several employees. The text file follows this scheme.

EmployeeName Department 20.00

I need an awk command with a variable that will calculate the daily salary. I also need each field separated with a tab and a dollar sign shown for the hourly and daily rates, as well as the /hr and /day trailing text. So, for example

      EmployeeName  Department    $20.00/hr    $160/day
      EmployeeName  Department    $50.00/hr    $400/day
      EmployeeName  Department    $200.00/hr   $1600/day 

I also need to total and display the hourly salary for all the workers with text that reads "workers earned a combined $889 (or whatever the total comes to) per hour.

I'm new to awk and I've done some googling, but I don't really know where to begin.

Atlas_21
  • 3
  • 2

4 Answers4

1
awk -v hpd=8 '
  { printf "%s\t%s\t%s\t$%.2f/hr\t$%.2f/day\n", $1, $2, $3, $4, $4 * hpd;
    ht += $4; # hourly total
  };

  END {
    printf "\nWorkers earned a combined $%.2f per hour\n", ht
  }
' input.txt
Adam    Adamson Accounting      $20.00/hr       $160.00/day
Iver    Iverson InfoTech        $50.00/hr       $400.00/day
Cary    Caryson ChiefExecutive  $200.00/hr      $1600.00/day
Mary    Maryson Maintenance     $15.00/hr       $120.00/day
Stan    Stanson SalesDept.      $10.00/hr       $80.00/day
Scot    Scotson SalesDept.      $10.00/hr       $80.00/day
Eric    Ericson Executive       $100.00/hr      $800.00/day
Enid    Enidson Executive       $100.00/hr      $800.00/day
Maye    Mayeson Maintenance     $15.00/hr       $120.00/day
Axel    Axelson Accounting      $21.00/hr       $168.00/day
Pete    Peteson PayrollDept.    $15.50/hr       $124.00/day
Mick    Mickson Marketing       $12.00/hr       $96.00/day
Iris    Irisson InfoTech        $55.00/hr       $440.00/day
Hank    Hankson HumanRes        $42.42/hr       $339.36/day

Workers earned a combined $665.92 per hour

The first block of code (i.e. inside the first pair of { and } curly braces) is run for every line of the input file (input.txt in this case). The END {...} block is only run once after all input has been read and processed.

You can change the number of hours per day by changing the hpd=8 part of the command line. I could have hard-coded it to 8, but I thought it was more interesting to make it a variable.

As an exercise, see if you can modify the final printf statement so that it also prints a daily total. Figuring this out will help you to understand what the printf statement is doing. Output should be something like:

Workers earned a combined $665.92 per hour or $5327.36 per day
cas
  • 1
  • 7
  • 119
  • 185
1
awk '{$NF="$"$NF"/hr " "$"$NF*8"/day";print $0}' filename

output

Adam Adamson Accounting $20.00/hr $160/day
Iver Iverson InfoTech $50.00/hr $400/day
Cary Caryson ChiefExecutive $200.00/hr $1600/day
Mary Maryson Maintenance $15.00/hr $120/day
Stan Stanson SalesDept. $10.00/hr $80/day
Scot Scotson SalesDept. $10.00/hr $80/day
Eric Ericson Executive $100.00/hr $800/day
Enid Enidson Executive $100.00/hr $800/day
Maye Mayeson Maintenance $15.00/hr $120/day
Axel Axelson Accounting $21.00/hr $168/day
Pete Peteson PayrollDept. $15.50/hr $124/day
Mick Mickson Marketing $12.00/hr $96/day
Iris Irisson InfoTech $55.00/hr $440/day
Hank Hankson HumanRes $42.42/hr $339.36/day
Praveen Kumar BS
  • 5,139
  • 2
  • 9
  • 14
  • Thank you for this. I'm learning and this is simple to follow along with to accomplish the first task. In several of my attempts I used a variation of NF and/or NR, but always come up with an error. I wasn't sure where to place things either, so I know that had something to do with it. The only issue here was that the last column wasn't spaced correctly for my specific file. After a few attempts of placing a tab character I finally realized where it needs to go. So, like this: "\t$"$NF*8". – Atlas_21 Nov 13 '21 at 13:58
0

Hard Way. For GNU awk only using multidimensional arrays. The format of the columns is preserved regardless of the length of their content(as when using the column -t utility). The delimiter is globally defined in the OFS variable:

awk -v pre="$" -v suf="/hr" '
        {hr+=$NF;
        for(i=1; i<=NF; i++) {
                row[NR][i]=$i
                l=length($i)
                if(l>len[i]) len[i]=l
                }
        }
END     {for(i in row){
                for(j in row[i])
                        printf("%-*s" OFS, (j==NF?4:0) + len[j],
                                j==NF? pre row[i][j] suf: row[i][j])
                print pre row[i][j] * 8 "/day"
                }
        print "\nworkers earned a combined $" hr " per hour"
        }
' OFS='\t' file

In the first part, the maximum width of each column is calculated and indented according to it when printing.

nezabudka
  • 2,376
  • 5
  • 15
-2

Does it need to be awk?

#!/bin/bash
while IFS='' read -r LinefromFile || [[ -n "${LinefromFile}" ]]; do
    a=($(echo "$LinefromFile"))
    printf "%-20s" $a[1] $a[2] $a[3] 
    printf "%-20s%.2f" $a[4] $((a[4] * 8))
    printf "\n"
done < "$1"


NerdyDeeds
  • 121
  • 5
  • 3
    Yes, it does need to be awk. or perl. or python. or almost any language that isn't shell. `bash` can only do **integer** calculations. e.g. the Hank Hankson line will produce an error: `42.42: syntax error: invalid arithmetic operator (error token is ".42")`. Similar for Pete Peteson. There are **many** reasons why using shell scripts to process data (instead of using shell to call other programs to do the processing) is a bad idea. This is just one of them. See also [Why is using a shell loop to process text considered bad practice?](https://unix.stackexchange.com/q/169716/7696) – cas Nov 13 '21 at 06:20