Space in PATH variable

Hi All,
I did a review of some threads to see if someone had come across this problem.

My system is an oracle virtual box solaris 10 installed on a windows 10 system.

Right now I am learning scripting and am just playing with the env variables.

I am trying to update the PATH to read from the oratab file and use it.

My problem: The result I get is not quite right in the little bash statement I had written. My new exported $PATH is echo'd and a space appears between the root path and the oracle path.

My oratab in /var/opt/oracle/oratab reads the following:

  
 SGCD:/export/home/oracle/app/oracle/product/12.1.0/dbhome_2:N 

Since my oracle profile reads ..../dbhome_1 I changed the "1" to a "2" in the oratab file here so as not to get both confused and to see which one is
actually getting copied. I am just learning this bash scripting.

The oracle env path is the following at the env cmd:

  
 PATH=/usr/bin:/bin:/export/home/oracle/app/oracle/product/12.1.0/dbhome_1/b

in and I am using the following command to cut it from the oratab file:

 
 ORACLE_HOME=`cat /var/opt/oracle/oratab|grep -v "^#"|cut -d ':' -f2`

output:

 /export/home/oracle/app/oracle/product/12.1.0/dbhome_2

The result I get is not quite right in the little bash statement I had written.

My new exported $PATH ( PATH=/usr/sbin/usr/bin:$ORACLE_HOME/bin ) is echo'd and a space appears between the root path and the oracle path right afterthe colon.

output:

 
 echo $PATH

 /usr/bin:/usr/sbin: /export/home/oracle/app/oracle/product/12.1.0/dbhome_2/bin

For the life of me I cannot figure out why this space appears above because it does not allow for other sql commands to be found and executed in my script.

Eventually i will add this to a loop statement to go thru the entire oratab file.

Any help would be appreciated.

Thanks in advance.

What editor are you using?
I tested your code on a AIX ( sorry that is all I have at the moment...) with ksh and cant recreate your issue... So to me nothing is wrong with your code unless there are some unprintable char ( which is often the case with files from windows... )

I am using the vi editor. thanks for your response.

What output do you get from the command:

grep -v "^#" /var/opt/oracle/oratab|od -bc

?

Not ignoring what Don has said (because that is very important), would you not be better using the IFS variable? The Input Field Separator (I think) is a way to chop up input in a more meaningful way to you, so you could perhaps:-

IFS=: read SID ORACLE_HOME YorN < <(grep -E "^SGCD:" /etc/oratab)

This should work in bash, but sadly I don't have a true ksh any more. The IFS setting as a colon : means that the output from the grep will be split up and you can read them into three variables, so you get the SID, the ORACLE_HOME that you really want and the Y or N value for it being auto-started. The variables you read are positional and the last variable gets everything to the end of the line, so if you miss out the YorN one, then $ORACLE_HOME
will be /export/home/oracle/app/oracle/product/12.1.0/dbhome_2:N which I assume you do not want.

In ksh, you might have to do this instead (untested) to get a similar result:-

grep -E "^SGCD:" /etc/oratab | read SID ORACLE_HOME YorN

I hope that this helps,
Robin

Good Morning Don,

Hope you had a nice 4th of July.

Here is the output that I found. It is a bit unusual.

 $ grep -v "^#" /var/opt/oracle/oratab|od -bc
0000000 012 012 012 012 104 103 107 123 072 057 145 170 160 157 162 164
          \n  \n  \n  \n   D   C   G   S   :   /   e   x   p   o   r   t
0000020 057 150 157 155 145 057 157 162 141 143 154 145 057 141 160 160
           /   h   o   m   e   /   o   r   a   c   l   e   /   a   p   p
0000040 057 157 162 141 143 154 145 057 160 162 157 144 165 143 164 057
           /   o   r   a   c   l   e   /   p   r   o   d   u   c   t   /
0000060 061 062 056 061 056 060 057 144 142 150 157 155 145 137 062 072
           1   2   .   1   .   0   /   d   b   h   o   m   e   _   2   :
0000100 116 040 040 040 040 040 012
           N                      \n
0000107

Regards

al

Now I see:
your grep -v "^#" finds the empty lines!
Use grep '^[^#]' instead, or even more precise, grep '^DCGS:'
And without the useless cat

ORACLE_HOME=`grep '^DCGS:' /var/opt/oracle/oratab | cut -d ':' -f2`
1 Like

Welcome to the world of scripting and its infinite possibilities. Let us go step by step, because you do several things wrongly here (as does every beginner - don't worry).

1) DO NOT use backticks - never! They are a leftover from a very old shell named "Bourne shell", to which bash is downwards compatible, hence the name "Bourne-again-shell". Bourne shell was the standard shell for UNIX systems in the early eighties, but these times are gone for some time now. Since you use bash you should use the modern way of "process substitution", which reads:

ORACLE_HOME=$(cat /var/opt/oracle/oratab|grep -v "^#"|cut -d ':' -f2)

2) You made the error of "useless use of cat". grep can read a file by itself and you don't need to dump the file contents into a data stream using cat . You can simply write:

ORACLE_HOME=$(grep -v "^#" /var/opt/oracle/oratab|cut -d ':' -f2)

This may look like a small point, but in fact it needs one process less to start. Starting a process is taxing on the resources of a system and while a single process more or less won't hurt at all if you use such a construct in an often-run loop the effects are considerable. It is never too early to start good habits and if you start doing it right in little scripts like this you will do it right once you start writing big ones either.

3) The grep command might not do what you think it does: grep filters lines. In your case you filter all lines starting with the character "#" - in fact you reversed this filter, so all lines NOT starting with "#" show up. But i.e empty lines or every other line not starting with "#" will show up too. I don't know your oratab file, but my suspicion is that your problem comes from there. Whenever you create regular expressions work on the following checklist:

  • does the regex match the correct lines/text parts? (Obvious)
  • are there misses i want matched? (false negatives)
  • are there matches i did not want to match? (false positives)

Even the most seasoned creators of regular expressions will not always get it right on the first try. The trick is to be persistent and try to imagine the cases mentioned in the checklist above and then modify the regexp accordingly until satisfaction is reached.

In your case i suppose you are not interested in "any non-comment lines", but in a specific line - the one starting with "SGCD", as rbatte1 already suggested. So your line should probably read:

ORACLE_HOME=$(grep '^SGCD:' /var/opt/oracle/oratab|cut -d ':' -f2)

4) in your scripts try to be as robust as possible. That is: try to anticipate possible problems and deal with them. Suppose, for instance, the oratab file does not contain a line starting with "SGCD:". Then the ORACLE_HOME would be empty and your PATH statement (supposing the rest works correct) would look like:

PATH=/path/one:/path/two::

You could avoid this by testing if a line you search for is even present at all and stop processing if it isn't:

if grep -q '^SGCD:' /var/opt/oracle/oratab ; then
           ORACLE_HOME=$(grep '^SGCD:' /var/opt/oracle/oratab|cut -d ':' -f2)
else
      echo "no SGCD-line found in oratab"
fi

and, finally, a last point: whenever you use grep and then cut you could use sed instead which can do alone what these two do combined:

ORACLE_HOME=$(sed '/^SGCD:/ s/^[^:]*:\([^:]*\):.*$/\1/' /var/opt/oracle/oratab)

I hope this helps.

bakunin

And again, sed by default reports the non-matching lines.
Quick fix:

ORACLE_HOME=$(sed -n '/^DGCS:/ s/^[^:]*:\([^:]*\):.*$/\1/p' /var/opt/oracle/oratab)

-n suppress default print
/p print if a match was found

1 Like

Yes, indeed. This was what i had in mind, but didn't write. Thank you for correcting it.

bakunin