使用 awk 解析 TNSNAMES.ORA 的最佳方法
Best means to parse TNSNAMES.ORA using awk
我构建了一个函数来解析 Tnsnames.ora 文件。我的问题是有更好的 awk 语句/查询可以给我想要的结果。
这是我要改进的语句,所以我将有一个更短的代码段:
awk "BEGIN{found=0}/${entry}/{found=1} {if (found) print }")
我想摆脱 for 循环并使用 AWK 来搜索和查找单个 TNSNAME。目前我正在计算 awk 命令的结果,直到我到达传递名称的最后一个 ) 。
findTnsname()
{
#!/bin/ksh
#inputs:
# : stanza title
# : Fully qualified input filename
# set to yes will echo how many were found
tnsnames=$(cat )
entries=$(echo "$tnsnames"| grep -i ".*="| awk '{print }')
eNames=$(echo "$entries" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/,/g')
ecount=$(echo "$entries" | wc -l | awk '{print }')
if [ "" = "yes" ] ; then
echo "# found ${ecount} entries - ${eNames} "
fi
for entry in $entries
{
#echo "#searching for ${entry}"
tt=$(echo "$tnsnames" | awk "BEGIN{found=0}/${entry}/{found=1} {if (found) print }")
t=0 # t for target, means the stanza has been found
open_parens=0
close_parens=0
if [[ -n $tt ]] ; then
echo "$tt" | while read -r i; do
if(( t == 1 )); then
echo "$i"
newline_ck=$(echo "$i" | egrep "^$" | wc -l | awk '{print }')
if(( newline_ck > 0 )); then
t=0
break
elif(( open_parens == close_parens && open_parens != 0 )); then
t=0
else
(( open_parens += $(echo "$i" | awk -F"(" '{print NF-1}') ))
(( close_parens += $(echo "$i" | awk -F")" '{print NF-1}') ))
#echo "# open ${open_parens} close ${close_parens} t ${t}"
fi
else
t=$(echo "$i" | egrep -i "^$entry" | wc | awk '{print }')
if(( t == 1 )); then
echo "$i"
fi
fi
done
else
echo "$entry does not exist in "
fi
}
}
结果如下所示:
findTnsname abc "$ORACLE_HOME/network/admin/tnsnames.ora"
ABC_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hosta.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABC_usr)
)
)
ABCT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostb.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABCt)
)
)
样本输入
DEF_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hosta.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEF_USR)
)
)
DEFT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostb.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEFT)
)
)
DEF_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostc.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEF_USR)
)
)
DEFT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostd.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEFT)
)
)
GHI_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hoste.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = GHI_USR)
)
)
GHIT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostf.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = GHIT)
)
)
ABC_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hosta.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABC_usr)
)
)
ABCT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostb.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABCt)
)
)
这可能是您要查找的内容,具体取决于我在您问题下的评论中提出的问题的答案:
如果您的输入记录之间始终如您在一条评论中所建议的那样有空行,那么您只需要:
$ awk -v key='abc' -v RS= -v ORS='\n\n' 'tolower([=10=])~tolower(key)' file
否则,如果他们有时不像您提供的示例输入那样:
$ cat tst.awk
!NF { next }
!/[()]/ { prt(); rec="" }
{ rec = rec [=11=] ORS }
END { prt() }
function prt() {
if ( tolower(rec) ~ tolower(key) ) {
print rec
}
}
$ awk -v key='abc' -f tst.awk file
ABC_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hosta.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABC_usr)
)
)
ABCT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostb.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABCt)
)
)
编辑 - 要更好地控制在何处搜索哪些字段以及打印什么内容,还需要考虑其他事项:
$ cat tst.awk
BEGIN { FS=RS; RS=""; ORS="\n" }
{
delete f
f["NAME"] =
sub(/[[:space:]]*=.*/,"",f["NAME"])
for (i=2; i<=NF; i++) {
n = split($i,tmp,/[ =()]+/)
for (j=n-2; j>1; j-=2) {
f[tmp[j]] = tmp[j+1]
}
}
prt()
}
function prt() {
for (tag in f) {
print tag "=<" f[tag] ">"
}
print "----"
}
.
$ awk -f tst.awk file
LOAD_BALANCE=<yes>
HOST=<hosta.some.company.com>
PROTOCOL=<TCP>
NAME=<DEF_USR.some.company.com>
SERVICE_NAME=<DEF_USR>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostb.some.company.com>
PROTOCOL=<TCP>
NAME=<DEFT.some.company.com>
SERVICE_NAME=<DEFT>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostc.some.company.com>
PROTOCOL=<TCP>
NAME=<DEF_USR.some.company.com>
SERVICE_NAME=<DEF_USR>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostd.some.company.com>
PROTOCOL=<TCP>
NAME=<DEFT.some.company.com>
SERVICE_NAME=<DEFT>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hoste.some.company.com>
PROTOCOL=<TCP>
NAME=<GHI_USR.some.company.com>
SERVICE_NAME=<GHI_USR>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostf.some.company.com>
PROTOCOL=<TCP>
NAME=<GHIT.some.company.com>
SERVICE_NAME=<GHIT>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hosta.some.company.com>
PROTOCOL=<TCP>
NAME=<ABC_USR.some.company.com>
SERVICE_NAME=<ABC_usr>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostb.some.company.com>
PROTOCOL=<TCP>
NAME=<ABCT.some.company.com>
SERVICE_NAME=<ABCt>
SERVER=<DEDICATED>
PORT=<1521>
----
我构建了一个函数来解析 Tnsnames.ora 文件。我的问题是有更好的 awk 语句/查询可以给我想要的结果。
这是我要改进的语句,所以我将有一个更短的代码段:
awk "BEGIN{found=0}/${entry}/{found=1} {if (found) print }")
我想摆脱 for 循环并使用 AWK 来搜索和查找单个 TNSNAME。目前我正在计算 awk 命令的结果,直到我到达传递名称的最后一个 ) 。
findTnsname()
{
#!/bin/ksh
#inputs:
# : stanza title
# : Fully qualified input filename
# set to yes will echo how many were found
tnsnames=$(cat )
entries=$(echo "$tnsnames"| grep -i ".*="| awk '{print }')
eNames=$(echo "$entries" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/,/g')
ecount=$(echo "$entries" | wc -l | awk '{print }')
if [ "" = "yes" ] ; then
echo "# found ${ecount} entries - ${eNames} "
fi
for entry in $entries
{
#echo "#searching for ${entry}"
tt=$(echo "$tnsnames" | awk "BEGIN{found=0}/${entry}/{found=1} {if (found) print }")
t=0 # t for target, means the stanza has been found
open_parens=0
close_parens=0
if [[ -n $tt ]] ; then
echo "$tt" | while read -r i; do
if(( t == 1 )); then
echo "$i"
newline_ck=$(echo "$i" | egrep "^$" | wc -l | awk '{print }')
if(( newline_ck > 0 )); then
t=0
break
elif(( open_parens == close_parens && open_parens != 0 )); then
t=0
else
(( open_parens += $(echo "$i" | awk -F"(" '{print NF-1}') ))
(( close_parens += $(echo "$i" | awk -F")" '{print NF-1}') ))
#echo "# open ${open_parens} close ${close_parens} t ${t}"
fi
else
t=$(echo "$i" | egrep -i "^$entry" | wc | awk '{print }')
if(( t == 1 )); then
echo "$i"
fi
fi
done
else
echo "$entry does not exist in "
fi
}
}
结果如下所示: findTnsname abc "$ORACLE_HOME/network/admin/tnsnames.ora"
ABC_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hosta.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABC_usr)
)
)
ABCT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostb.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABCt)
)
)
样本输入
DEF_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hosta.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEF_USR)
)
)
DEFT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostb.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEFT)
)
)
DEF_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostc.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEF_USR)
)
)
DEFT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostd.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEFT)
)
)
GHI_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hoste.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = GHI_USR)
)
)
GHIT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostf.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = GHIT)
)
)
ABC_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hosta.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABC_usr)
)
)
ABCT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostb.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABCt)
)
)
这可能是您要查找的内容,具体取决于我在您问题下的评论中提出的问题的答案:
如果您的输入记录之间始终如您在一条评论中所建议的那样有空行,那么您只需要:
$ awk -v key='abc' -v RS= -v ORS='\n\n' 'tolower([=10=])~tolower(key)' file
否则,如果他们有时不像您提供的示例输入那样:
$ cat tst.awk
!NF { next }
!/[()]/ { prt(); rec="" }
{ rec = rec [=11=] ORS }
END { prt() }
function prt() {
if ( tolower(rec) ~ tolower(key) ) {
print rec
}
}
$ awk -v key='abc' -f tst.awk file
ABC_USR.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hosta.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABC_usr)
)
)
ABCT.some.company.com =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hostb.some.company.com)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ABCt)
)
)
编辑 - 要更好地控制在何处搜索哪些字段以及打印什么内容,还需要考虑其他事项:
$ cat tst.awk
BEGIN { FS=RS; RS=""; ORS="\n" }
{
delete f
f["NAME"] =
sub(/[[:space:]]*=.*/,"",f["NAME"])
for (i=2; i<=NF; i++) {
n = split($i,tmp,/[ =()]+/)
for (j=n-2; j>1; j-=2) {
f[tmp[j]] = tmp[j+1]
}
}
prt()
}
function prt() {
for (tag in f) {
print tag "=<" f[tag] ">"
}
print "----"
}
.
$ awk -f tst.awk file
LOAD_BALANCE=<yes>
HOST=<hosta.some.company.com>
PROTOCOL=<TCP>
NAME=<DEF_USR.some.company.com>
SERVICE_NAME=<DEF_USR>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostb.some.company.com>
PROTOCOL=<TCP>
NAME=<DEFT.some.company.com>
SERVICE_NAME=<DEFT>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostc.some.company.com>
PROTOCOL=<TCP>
NAME=<DEF_USR.some.company.com>
SERVICE_NAME=<DEF_USR>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostd.some.company.com>
PROTOCOL=<TCP>
NAME=<DEFT.some.company.com>
SERVICE_NAME=<DEFT>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hoste.some.company.com>
PROTOCOL=<TCP>
NAME=<GHI_USR.some.company.com>
SERVICE_NAME=<GHI_USR>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostf.some.company.com>
PROTOCOL=<TCP>
NAME=<GHIT.some.company.com>
SERVICE_NAME=<GHIT>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hosta.some.company.com>
PROTOCOL=<TCP>
NAME=<ABC_USR.some.company.com>
SERVICE_NAME=<ABC_usr>
SERVER=<DEDICATED>
PORT=<1521>
----
LOAD_BALANCE=<yes>
HOST=<hostb.some.company.com>
PROTOCOL=<TCP>
NAME=<ABCT.some.company.com>
SERVICE_NAME=<ABCt>
SERVER=<DEDICATED>
PORT=<1521>
----