Reputation: 305
I am trying to print out the contents of a TNS entry from the tnsnames.ora file to make sure it is correct from an Oracle RAC environment.
So if I do something like:
grep -A 4 "mydb.mydomain.com" $ORACLE_HOME/network/admin/tnsnames.ora
I will get back:
mydb.mydomain.com =
(DESCRIPTION =
(ADDRESS =
(PROTOCOL = TCP)(HOST = myhost.mydomain.com)(PORT = 1521))
(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME=mydb)))
Which is what I want. Now I have an environment variable being set for the JDBC connection string by an external program when the shell script gets called like:
export [email protected]:1521/mydb
So I need to get TNS alias mydb.mydomain.com out of the above string. I'm not sure how to do multiple matches and reorder the matches with regex and need some help.
grep @.+: $DB_URL
I assume will get the
@myhost.mydomain.com:
but I'm looking for
mydb.mydomain.com
So I'm stuck at this part. How do I get the TNS alias and then pipe/combine it with the initial grep to display the text for the TNS entry?
Thanks
update:
@mklement0 @Walter A - I tried your ways but they are not exactly what I was looking for.
echo "@myhost.mydomain.com:1521/mydb" | grep -Po "@\K[^:]*"
echo "@myhost.mydomain.com:1521/mydb" | sed 's/.*@\(.*\):.*/\1/'
echo "@myhost.mydomain.com:1521/mydb" | cut -d"@" -f2 | cut -d":" -f1
echo "@myhost.mydomain.com:1521/mydb" | tr "@:" "\t" | cut -f2
echo "@myhost.mydomain.com:1521/mydb" | awk -F'[@:]' '{ print $2 }'
All these methods get me back: myhost.mydomain.com
What I am looking for is actually: mydb.mydomain.com
Upvotes: 2
Views: 1040
Reputation: 439852
Note:
- For brevity, the commands below use bash
/ksh
/zsh
here-string syntax to send strings to stdin (<<<"$var"
). If your shell doesn't support this, use printf %s "$var" | ...
instead.
The following awk
command will extract the desired string (mydb.mydomain.com
) from $DB_URL
(@myhost.mydomain.com:1521/mydb
):
awk -F '[@:/]' '{ sub("^[^.]+", "", $2); print $4 $2 }' <<<"$DB_URL"
-F'[@:/]'
tells awk
to split the input into fields by either @
or :
or /
. With your input, this means that the field of interest are part of the second field ($2
) and the fourth field ($4
). The sub()
call removes the first .
-based component from $2
, and the print
call pieces together the result.To put it all together:
domain=$(awk -F '[@:/]' '{ sub("^[^.]+", "", $2); print $4 $2 }' <<<"$DB_URL")
grep -F -A 4 "$domain" "$ORACLE_HOME/network/admin/tnsnames.ora"
You don't strictly need intermediate variable $domain
, but I've added it for clarity.
Note how -F
was added to grep
to specify that the search term should be treated as a literal, so that characters such as .
aren't treated as regex metacharacters.
Alternatively, for more robust matching, use a regex that is anchored to the start of the line with ^
, and \
-escape the .
chars (using shell parameter expansion) to ensure their treatment as literals:
grep -A 4 "^${domain//./\.}" "$ORACLE_HOME/network/admin/tnsnames.ora"
Upvotes: 2
Reputation: 20032
You can get a part of a string with
# Only GNU-grep
echo "@myhost.mydomain.com:1521/mydb" | grep -Po "@\K[^:]*"
# or
echo "@myhost.mydomain.com:1521/mydb" | sed 's/.*@\(.*\):.*/\1/'
# or
echo "@myhost.mydomain.com:1521/mydb" | cut -d"@" -f2 | cut -d":" -f1
# or, when the string already is in a var
echo "${DB_URL#*@}" | cut -d":" -f1
# or using a temp var
tmpvar="${DB_URL#*@}"
echo "${tmpvar%:*}"
I had skipped the alternative awk, that was given by @mklement0 already:
echo "@myhost.mydomain.com:1521/mydb" | awk -F'[@:]' '{ print $2 }'
The awk solution is straight-forward, when you want to use the same approach without awk you can do something like
echo "@myhost.mydomain.com:1521/mydb" | tr "@:" "\t" | cut -f2
or the ugly
echo "@myhost.mydomain.com:1521/mydb" | (IFS='@:' read -r _ url _; echo "$url")
What is happening here?
After introducing the new IFS I want to take the second word of the input. The first and third word(s) are caught in the dummy var's _
(you could have named them dummyvar1
and dummyvar2
). The pipe |
creates a subprocess, so you need ()
to hold reading and displaying the var url
in the same process.
Upvotes: 2