0

I am trying to utilize a combination of awk/sed to print certain fields within a given csv. I am running into a problem with getting awk to recognize my given parameters (e.g. ./printcsv.sh 3 5 - parameters being 3 and 5 and trying to print columns 3 and 5 of a csv via awk) in the code.

#! /bin/bash

read -p "What file would you like to print? " file
read -p "What directory is this file located in? " directory

cd $directory

touch readcsv.txt

for (( i = 1; i <= $#; i=i+1 ))
    do
        cat $file | awk -F "," -v var=${i} 'NR==2 {print $var }' "$directory"/"$file" >> readcsv.txt

    done

cat readcsv.txt

rm readcsv.txt

I've thought or creating a temporary .txt file where I'd append the printed fields to, in order to cat that .txt file to be read, but I'm having trouble (probably for a lack of knowledge of sed) of creating a table in the file, as the output is just two columns right after each other (an extremely long column). Also, I don't know if the issue lies in the "for" loop that I created, or the way I'm trying to expand the variable "i", but even if I set my parameters to say 3 and 5, my hope would be that $1 would then translate to the parameter 3 (therefore column 3 in the csv), instead it still is translating to column 1 in the awk command.

Just as a frame of reference, I am very new to Bash, all self taught through online courses, which can only help so much until you get into non-course examples.

Michael
  • 11
  • 1
  • 1
    wrt `I am trying to utilize a combination of awk/sed` - you never need sed when you're using awk. You should run your code through shellcheck (e.g. https://www.shellcheck.net/) and read [why-is-using-a-shell-loop-to-process-text-considered-bad-practice](https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice), https://mywiki.wooledge.org/Quotes, and http://porkmail.org/era/unix/award.html. – Ed Morton Mar 10 '20 at 14:17
  • While the answers below show you how to achieve your task efficiently, you may still want to understand how to loop on command arguments anyway. Well `${i}` is just the same as `$i`, which expands to the value of the iteration variable `i`. If you actually want to expand to the i-th positional parameter, then you have to add a level of indirection using `${!i}`. If you only need parameter values, without indices, then you can use a simpler syntax `for arg in "$@"; do echo doing something with arg "$arg"...; done`. – luciole75w Mar 10 '20 at 17:24

2 Answers2

1

To print columns 3 and 5 of a csv via awk this is all you need:

num1=3
num2=5

awk -v list="$num1 $num2" '
    BEGIN {
        n = split(list,cols)
        FS=OFS=","
    }
    {
        for (i=1; i<=n; i++) {
            printf "%s%s", $(cols[i]), (i<n ? OFS : ORS)
        }
    }
' file

and, in case you care, to print from 3 to 5 would be:

awk -v beg="$num1" -v end="$num2" '
    BEGIN {
        FS=OFS=","
    }
    {
        for (i=beg; i<=end; i++) {
            printf "%s%s", $i, (i<end ? OFS : ORS)
        }
    }
' file

The above is assuming you have a very simple CSV, otherwise see whats-the-most-robust-way-to-efficiently-parse-csv-using-awk

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
1

try to use the build-ins before you roll your own.

for example, cut will do what you need with already

$ cut -d, -f3,4,5 file

in your script if the script input argument is "3,4,5" you can use this

cut -d, -f"$@" "$file"

will display the columns selected, no need to create a temp file. As a side benefit, it supports ranges as well, so you can use "3-5" input format as well.

karakfa
  • 66,216
  • 7
  • 41
  • 56