2016-04-14 96 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 ='@ :.''作爲用戶的練習。 –

相關問題