正则表达式 w/grep 反对 tnsnames.ora
Regex w/grep against tnsnames.ora
我正在尝试从 tnsnames.ora 文件打印出 TNS 条目的内容,以确保它在 Oracle RAC 环境中是正确的。
所以如果我做类似的事情:
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)))
这就是我想要的。现在,当 shell 脚本被调用时,我有一个外部程序为 JDBC 连接字符串设置的环境变量:
export $DB_URL=@myhost.mydomain.com:1521/mydb
所以我需要从上面的字符串中获取 TNS 别名 mydb.mydomain.com。我不确定如何使用正则表达式进行多重匹配和重新排序匹配,需要一些帮助。
grep @.+: $DB_URL
我假设会得到
@myhost.mydomain.com:
但我正在寻找
mydb.mydomain.com
所以我卡在了这一部分。我如何获取 TNS 别名,然后 pipe/combine 它与初始 grep 一起显示 TNS 条目的文本?
谢谢
更新:
@mklement0 @Walter A - 我试过你的方法,但它们并不是我想要的。
echo "@myhost.mydomain.com:1521/mydb" | grep -Po "@\K[^:]*"
echo "@myhost.mydomain.com:1521/mydb" | sed 's/.*@\(.*\):.*//'
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 }'
所有这些方法让我回来了:myhost.mydomain.com
我要找的其实是:mydb.mydomain.com
注:
- 为简洁起见,以下命令使用 bash
/ksh
/zsh
here-string 语法将字符串发送到标准输入 (<<<"$var"
)。如果您的 shell 不支持此功能,请改用 printf %s "$var" | ...
。
以下 awk
命令将从 $DB_URL
(@myhost.mydomain.com:1521/mydb
) 中提取所需的字符串 (mydb.mydomain.com
):
awk -F '[@:/]' '{ sub("^[^.]+", "", ); print }' <<<"$DB_URL"
-F'[@:/]'
告诉 awk
通过 @
或 :
或 /
将输入拆分为字段。根据您的输入,这意味着感兴趣的字段是 second 字段 (</code>) 的 <em>part</em> 和第四个字段 (<code>
). sub()
调用从 </code> 中删除第一个基于 <code>.
的组件,print
调用将结果拼凑在一起。
将它们放在一起:
domain=$(awk -F '[@:/]' '{ sub("^[^.]+", "", ); print }' <<<"$DB_URL")
grep -F -A 4 "$domain" "$ORACLE_HOME/network/admin/tnsnames.ora"
严格来说,您不需要中间变量 $domain
,但为了清楚起见,我添加了它。
请注意如何将 -F
添加到 grep
以指定应将搜索词视为 文字 ,以便 .
等字符不存在t 被视为正则表达式元字符。
或者,为了更稳健的匹配,使用 regex 锚定到带有 ^
和 \
-[= 的行的开头52=]转义 .
个字符(使用 shell parameter expansion)以确保将它们作为文字处理:
grep -A 4 "^${domain//./\.}" "$ORACLE_HOME/network/admin/tnsnames.ora"
您可以使用
获取字符串的一部分
# Only GNU-grep
echo "@myhost.mydomain.com:1521/mydb" | grep -Po "@\K[^:]*"
# or
echo "@myhost.mydomain.com:1521/mydb" | sed 's/.*@\(.*\):.*//'
# 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 }'
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 之后,我想取输入的第二个词。第一个和第三个词包含在虚拟变量的 _
中(您可以将它们命名为 dummyvar1
和 dummyvar2
)。管道 |
创建一个子进程,因此您需要 ()
在同一进程中读取和显示变量 url
。
我正在尝试从 tnsnames.ora 文件打印出 TNS 条目的内容,以确保它在 Oracle RAC 环境中是正确的。
所以如果我做类似的事情:
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)))
这就是我想要的。现在,当 shell 脚本被调用时,我有一个外部程序为 JDBC 连接字符串设置的环境变量:
export $DB_URL=@myhost.mydomain.com:1521/mydb
所以我需要从上面的字符串中获取 TNS 别名 mydb.mydomain.com。我不确定如何使用正则表达式进行多重匹配和重新排序匹配,需要一些帮助。
grep @.+: $DB_URL
我假设会得到
@myhost.mydomain.com:
但我正在寻找
mydb.mydomain.com
所以我卡在了这一部分。我如何获取 TNS 别名,然后 pipe/combine 它与初始 grep 一起显示 TNS 条目的文本?
谢谢
更新:
@mklement0 @Walter A - 我试过你的方法,但它们并不是我想要的。
echo "@myhost.mydomain.com:1521/mydb" | grep -Po "@\K[^:]*"
echo "@myhost.mydomain.com:1521/mydb" | sed 's/.*@\(.*\):.*//'
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 }'
所有这些方法让我回来了:myhost.mydomain.com
我要找的其实是:mydb.mydomain.com
注:
- 为简洁起见,以下命令使用 bash
/ksh
/zsh
here-string 语法将字符串发送到标准输入 (<<<"$var"
)。如果您的 shell 不支持此功能,请改用 printf %s "$var" | ...
。
以下 awk
命令将从 $DB_URL
(@myhost.mydomain.com:1521/mydb
) 中提取所需的字符串 (mydb.mydomain.com
):
awk -F '[@:/]' '{ sub("^[^.]+", "", ); print }' <<<"$DB_URL"
-F'[@:/]'
告诉awk
通过@
或:
或/
将输入拆分为字段。根据您的输入,这意味着感兴趣的字段是 second 字段 (</code>) 的 <em>part</em> 和第四个字段 (<code>
).sub()
调用从</code> 中删除第一个基于 <code>.
的组件,print
调用将结果拼凑在一起。
将它们放在一起:
domain=$(awk -F '[@:/]' '{ sub("^[^.]+", "", ); print }' <<<"$DB_URL")
grep -F -A 4 "$domain" "$ORACLE_HOME/network/admin/tnsnames.ora"
严格来说,您不需要中间变量 $domain
,但为了清楚起见,我添加了它。
请注意如何将 -F
添加到 grep
以指定应将搜索词视为 文字 ,以便 .
等字符不存在t 被视为正则表达式元字符。
或者,为了更稳健的匹配,使用 regex 锚定到带有 ^
和 \
-[= 的行的开头52=]转义 .
个字符(使用 shell parameter expansion)以确保将它们作为文字处理:
grep -A 4 "^${domain//./\.}" "$ORACLE_HOME/network/admin/tnsnames.ora"
您可以使用
获取字符串的一部分# Only GNU-grep
echo "@myhost.mydomain.com:1521/mydb" | grep -Po "@\K[^:]*"
# or
echo "@myhost.mydomain.com:1521/mydb" | sed 's/.*@\(.*\):.*//'
# 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 }'
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 之后,我想取输入的第二个词。第一个和第三个词包含在虚拟变量的 _
中(您可以将它们命名为 dummyvar1
和 dummyvar2
)。管道 |
创建一个子进程,因此您需要 ()
在同一进程中读取和显示变量 url
。