How do I cat into an array or is it not possible?

Hi,

Normally, I would do

cat /etc/oratab | grep -v "^#" | grep -v "^*" > /tmp/oratab.00
while read line
do
   echo $line
done < /tmp/oratab.00

I want to know whether it is possible to use an array instead of re-directing it to file?

As a test, I did something like below:

#!/bin/ksh

cat /tmp/oratab.00 | grep -v "^#" | grep -v "^*" > /tmp/oratab.01
while read line
do
   echo $line
done < /tmp/oratab.01

echo ""
echo "###########"
echo ""

set -A oratab_array
oratab_array
[*]=`cat /tmp/oratab.00 | grep -v "^#" | grep -v "^*"`
oratab_array_count=${#oratab_array[@]}
echo "oratab_array_count = ${oratab_array_count}"

echo ""
echo "###########"
echo ""

exit 0

Output from a sample run below:

mnl1:/opt/oracle/9.2.0.8:N:::N
mkt1:/opt/oracle/11.2.0:N:::N
cal1:/opt/oracle/11.2.0:N:::N

###########

oratab_array_count = 1

###########

/tmp/oratab.00 as below:

#
# This file is used by ORACLE utilities. It is created by root.sh
# and updated by the Database Configuration Assistant when creating
# a database.
# A colon, ':', is used as the field terminator. A new line terminates
# the entry. Lines beginning with a pound sign, '#', are comments.
#
# Entries are of the form:
# $ORACLE_SID:$ORACLE_HOME:<N|Y>:
#
# The first and second fields are the system identifier and home
# directory of the database respectively. The third filed indicates
# to the dbstart utility that the database should , "Y", or should not,
# "N", be brought up at system boot time.
#
# Field #5 is the db type (""=standalone database, P=primary, S=standby)
# Field #6 is used by the scripts in /nas_mnt/common/dba_utils/PS/patrol
#
# Multiple entries with the same $ORACLE_SID are not allowed.
#
#
*:/opt/oracle/9.2.0.8:N
mnl1:/opt/oracle/9.2.0.8:N:::N
mkt1:/opt/oracle/11.2.0:N:::N
cal1:/opt/oracle/11.2.0:N:::N

Note that oratab_array_count is 1. Am expecting to have 3 but I assume what's happening is the result of cat | grep is being treated as one single line? How do I get it to treat them as individual array members?

Feedback much appreciated. Thanks in advance.

You could redirect into a while loop using something like this:

cat /etc/oratab | while read -a L ; do
   echo ${L[0]} etc...
done
cat /etc/oratab | while read file ; do i=$((${i:=-1} + 1)) ; lines[$i]="$file" ; done

If you have bash you may be able to use mapfile .

ksh:

# set -A ARR $(grep -vE "^#|^\*" oratab)
# echo ${ARR[0]}
"mnl1:/opt/oracle/9.2.0.8:N:::N"
# echo ${ARR[1]}
"mkt1:/opt/oracle/11.2.0:N:::N"
# echo ${ARR[2]}
"cal1:/opt/oracle/11.2.0:N:::N"

Assuming that there are no spaces and/or tabs in the lines:

set -A arr $(sed '/^[*#]/d' file)
echo ${#arr[*]}
3
echo ${arr[0]}
mnl1:/opt/oracle/9.2.0.8:N:::N
echo ${arr[1]}
mkt1:/opt/oracle/11.2.0:N:::N
echo ${arr[2]}
cal1:/opt/oracle/11.2.0:N:::N

EDIT: Oops..similar solution already provided by zaxxon.

Here is how i'd do that :

while read line ; do 

  array[${#array[@]}]="$line"

done <<<"$(grep -vE "^[#|*]" test.txt)"

And here is what inside the array after :

bash-3.2$ echo ${array[0]}
mnl1:/opt/oracle/9.2.0.8:N:::N
bash-3.2$ echo ${array[1]}
mkt1:/opt/oracle/11.2.0:N:::N
bash-3.2$ echo ${array[2]}
cal1:/opt/oracle/11.2.0:N:::N

EDIT : i've been caught in UUOC ! Shame on me!!! I updated my mistake.

There's another option without using an array, you can set the $1 $2 ... parameters.

OLDIFS="$IFS"
IFS=$'\n' # Set IFS to newline
        set -- `grep -v "^#" /etc/oratab | grep -v "^*"`
IFS="$OLDIFS"

echo "$1"
echo "$2"

See also useless use of cat. Grep does not need cat's help to read a file.