-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
  • 78,579
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
  • 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,428
  • 6
  • 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? – cas Nov 13 '21 at 06:20