2016-04-14 92 views
2

我试图从tnsnames.ora文件打印出TNS条目的内容,以确保它在Oracle RAC环境中正确。对tnsnames.ora的正则表达式w/grep

所以,如果我这样做:

grep -A 4 "mydb.mydomain.com" $ORACLE_HOME/network/admin/tnsnames.ora 

我会回来:

mydb.mydomain.com = 
(DESCRIPTION = 
    (ADDRESS = 
    (PROTOCOL = TCP)(HOST = myhost.mydomain.com)(PORT = 1521)) 
  (CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME=mydb))) 

这就是我想要的。现在我有一个环境变量被设置为通过外部程序的JDBC连接字符串时shell脚本被调用,如:

export [email protected]:1521/mydb 

所以我需要得到TNS别名mydb.mydomain.com出上面的字符串的。我不知道如何做多个匹配,并用正则表达式重新排序匹配,需要一些帮助。

grep @.+: $DB_URL 

我相信会得到

@myhost.mydomain.com: 

,但我在寻找

mydb.mydomain.com 

所以我坚持在这一部分。如何获取TNS别名,然后将其与初始grep进行管道/组合,以显示TNS条目的文本?

感谢


更新:

@ mklement0 @Walter A - 我想你的方式,但他们不正是我一直在寻找。

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 }' 

所有这些方法让我回到:myhost.mydomain.com

其实就是我在寻找:mydb.mydomain.com

回答

2

注:
- 为简洁起见,以下命令使用bash/ksh/zshhere-string语法向stdin发送字符串(<<<"$var")。如果你的shell不支持这个,请改用printf %s "$var" | ...

以下awk命令将提取从$DB_URL所需字符串(mydb.mydomain.com)(@myhost.mydomain.com:1521/mydb):

awk -F '[@:/]' '{ sub("^[^.]+", "", $2); print $4 $2 }' <<<"$DB_URL" 
  • -F'[@:/]'告诉awk通过向输入分成字段或者@:/ 。通过您的输入,这意味着感兴趣的字段是的部分第二个字段($2)和第四字段($4)。sub()调用从$2中删除第一个.的组件,并将print组合在一起调用结果。

为了把它放在一起:

domain=$(awk -F '[@:/]' '{ sub("^[^.]+", "", $2); print $4 $2 }' <<<"$DB_URL") 
grep -F -A 4 "$domain" "$ORACLE_HOME/network/admin/tnsnames.ora" 

你不严格需要中间变量$domain,但我已经添加了它的清晰度。 请注意如何将-F添加到grep以指定将搜索项视为文字,以便诸如.之类的字符不被视为正则表达式元字符。

或者,对于更稳健的匹配,使用正则表达式锚定到该行的开始与^,和\ - 逃逸.字符(使用壳parameter expansion),以确保他们的治疗作为文字:

grep -A 4 "^${domain//./\.}" "$ORACLE_HOME/network/admin/tnsnames.ora" 
+0

好的,我看到你最近的更新......它似乎按照预期工作。谢谢! – dave111

+0

@ dave111:很高兴听到它。您的问题首先得到了很好的介绍,但是,正如您所看到的,“mydb”和“myhost”之间的相似性导致我和Walter A错过了这一差异。注意自我:仔细阅读。对你的建议:或许明确地强调你的问题中人们可能忽视的东西。 – mklement0

2

你可以得到一个字符串的一部分与

# 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%:*}" 

我跳过替代awk中,这是由@ mklement0已经给出:

echo "@myhost.mydomain.com:1521/mydb" | awk -F'[@:]' '{ print $2 }' 

awk的解决方法是直接的,当你想使用没有awk的,你可以这样做同样的方式

echo "@myhost.mydomain.com:1521/mydb" | tr "@:" "\t" | cut -f2 

或丑陋

echo "@myhost.mydomain.com:1521/mydb" | (IFS='@:' read -r _ url _; echo "$url") 

这里发生了什么? 引入新的IFS后,我想要输入第二个单词。第一个和第三个单词被抓到了虚拟变种的_(你可以命名为dummyvar1dummyvar2)。管道|创建了一个子流程,因此您需要()来读取和显示同一过程中的变量url

+0

++显示如此多的选项,但是您也可以使用'awk -F'[@:]'{print $ 2}'。 – mklement0

+0

原来,我们最初都错过了OP不仅仅想要一个直接的子字符串提取,而是希望'myhost'从提取的字符串中的输入字符串的_end_替换为'mydb'。 – mklement0

+1

由于awk已经解决了它,所以我会留下一个解决方案,使用'sed'或'IFS ='@ :.''作为用户的练习。 –

相关问题