substancev
substancev

Reputation: 19

How do i echo specific rows and columns from csv's in a variable?

The below script:

#!/bin/bash
otscurrent="
AAA,33854,4528,38382,12
BBB,83917,12296,96213,13
CCC,20399,5396,25795,21
DDD,27198,4884,32082,15
EEE,2472,981,3453,28
FFF,3207,851,4058,21
GGG,30621,4595,35216,13
HHH,8450,1504,9954,15
III,4963,2157,7120,30
JJJ,51,59,110,54
KKK,87,123,210,59
LLL,573,144,717,20
MMM,617,1841,2458,75
NNN,234,76,310,25
OOO,12433,1908,14341,13
PPP,10627,1428,12055,12
QQQ,510,514,1024,50
RRR,1361,687,2048,34
SSS,1,24,25,96
TTT,0,5,5,100
UUU,294,1606,1900,85
"

IFS="," array1=(${otscurrent})

echo ${array1[4]}

Prints:

$ ./test.sh 
12
BBB

I'm trying to get it to just print 12... And I am not even sure how to make it just print row 5 column 4

The variable is an output of a sqlquery that has been parsed with several sed commands to change the formatting to csv.

otscurrent="$(sqlplus64 user/password@dbserverip/db as sysdba @query.sql |
 sed '1,11d; /^-/d; s/[[:space:]]\{1,\}/,/g; $d' |
 sed '$d'|sed '$d'|sed '$d' | sed '$d' |
 sed 's/Used,MB/Used MB/g'  |
 sed 's/Free,MB/Free MB/g' |
 sed 's/Total,MB/Total MB/g' |
 sed 's/Pct.,Free/Pct. Free/g' |
 sed '1b;/^Name/d' |
 sed '/^$/d'
)"

Ultimately I would like to be able to call on a row and column and run statements on the values.

Initially i was piping that into :

awk -F "," 'NR>1{ if($5 < 10)  {   printf "%-30s%-10s%-10s%-10s%-10s\n", $1,$2,$3,$4,$5"%";  } else  { echo "Nothing to do" } }')"

Which works but I couldn't run commands from if else ... or atleaste I didn't know how.

Upvotes: 0

Views: 517

Answers (3)

Ed Morton
Ed Morton

Reputation: 203368

All you need to print the value of the 4th column on the 5th row is:

$ awk -F, 'NR==5{print $4}' <<< "$otscurrent"
3453

and just remember that in awk row (record) and column (field) numbers start at 1, not 0. Some more examples:

$ awk -F, 'NR==1{print $5}' <<< "$otscurrent"
12

$ awk -F, 'NR==2{print $1}' <<< "$otscurrent"
BBB

$ awk -F, '$5 > 50' <<< "$otscurrent"
JJJ,51,59,110,54
KKK,87,123,210,59
MMM,617,1841,2458,75
SSS,1,24,25,96
TTT,0,5,5,100
UUU,294,1606,1900,85

If you'd like to avoid all of the complexity and simply parse your SQL output to produce what you want without 20 sed commands in between, post a new question showing the raw sqlplus output as the input and what you want finally output and someone will post a brief, clear, simple, efficient awk script to do it all at one time, or maybe 2 commands if you still want an intermediate CSV for some reason.

Upvotes: 0

Charles Duffy
Charles Duffy

Reputation: 295373

If you have bash 4.0 or newer, an associative array is an appropriate way to store data in this kind of form.

otscurrent=${otscurrent#$'\n'} # strip leading newline present in your sample data

declare -A data=( )

row=0
while IFS=, read -r -a line; do
  for idx in "${!line[@]}"; do
    data["$row,$idx"]=${line[$idx]}
  done
  (( row += 1 ))
done <<<"$otscurrent"

This lets you access each individual item:

echo "${data[0,0]}" # first field of first line
echo "${data[9,0]}" # first field of tenth line
echo "${data[9,1]}" # second field of tenth line

Upvotes: 2

John1024
John1024

Reputation: 113834

"I'm trying to get it to just print 12..."

The issue is that IFS="," splits on commas and there is no comma between 12 and BBB. If you want those to be separate elements, add a newline to IFS. Thus, replace:

IFS="," array1=(${otscurrent})

With:

IFS=$',\n' array1=(${otscurrent})

Output:

$ bash test.sh
12

Upvotes: 1

Related Questions