regex on tnsnames.ora - regex

my tnsnames.ora file has 2 formats :
db_cl =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = a55)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = cl)
)
)
dbcd =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = a66 )(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = cd)
)
)
myx5=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = v55)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = x5)
)
)
i want to get the hostname of a specific service_name or sid. in some cases it is sid and in some cases it is service_name. what should i search with grep in order to get the hostname? In this example i want to get the string "host_name".
****UPDATE****
I ALSO NEED THE db_name2, if someone can help

If perl is available try this command:
perl -nle 'BEGIN{$service = shift}
$host = $1 if /HOST\s*=\s*([^\s\)]+)/i;
print $host if /\((SID|SERVICE_NAME)\s*=\s*$service\)/;
' blabla tnsnames.ora
It stores the last host value found in HOST = ... and prints it when encounters (**SID/SERVICE_NAME** = blabla)

#drf: try:
awk '/HOST/{sub(/).*/,"",$(NF-2));print $(NF-2)}' Input_file
Simply looking for string HOST for each line then substituting the ).* from the 2nd last filed of the line where awk matches the string HOST in it, it should give you host_name then.
EDIT: For looking for a specific SID or service name try:
awk '/HOST/{sub(/).*/,"",$(NF-2));HOST=$(NF-2);next} /SID/{print HOST}'
Change SID with sid or service name which you want to search and it should work then.
EDIT2:
awk '/db_name/{sub(/=/,"",$1);DB=$1}/HOST/{sub(/).*/,"",$(NF-2));HOST=$(NF-2);next} /chumma/{print DB ORS HOST}'
EDIT3:
awk '{gsub(/\)|\(/,"");;for(i=1;i<=NF;i++){if($i=="HOST"){host=$(i+1)};if($NF=="cd"){val="DB_NAME= "$1", HOST_NAME= "host",SID/SERVICE_NAME= "$NF}};if(val){print val;val=""}}' Input_file
OR(non-one liner form of solution too as follows):
awk '{gsub(/\)|\(/,"");
for(i=1;i<=NF;i++){
if($i=="HOST"){
host=$(i+1)
};
if($NF=="cd") {
val="DB_NAME= "$1", HOST_NAME= "host",SID/SERVICE_NAME= "$NF
}
};
if(val) {
print val;
val=""
}
}
' Input_file
You could put "cd"''s place another service or ssid which you want to search too in above code.

Related

conditional search and replace differently in sed

This content is in text.txt for testing, I am going to rewrite bundle identifier in pipeline.
Current Behavior:
All PRODUCT_BUNDLE_IDENTIFIER will be replaced to "abc" if execute this command.
sed -i -e "s/PRODUCT_BUNDLE_IDENTIFIER =.*/PRODUCT_BUNDLE_IDENTIFIER = abc;/g" text.txt
Expectation:
However, I would like to change PRODUCT_BUNDLE_IDENTIFIER separately, Eg. from BundleA to BundleZ and from BundleB to BundleX etc. How can i use sed command to match regex and replace them with different values?
Content in text.txt:
{
2D02E40000B4A5E006451C7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_BUNDLE_IDENTIFIER = "BundleA";
};
name = Debug;
};
2D02E4981E0000006451C7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_BUNDLE_IDENTIFIER = "BundleB";
};
name = Release;
};
}

AWK change field separator multiple times

I have the following sample code below; for ease of testing I have combined the text of a few files into one. Usually this script would use the find command to filter through each subdirectory looking for versions.tf and run AWK on each one.
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "> 2.0.0"
}
}
required_version = ">= 0.13"
}
terraform {
required_providers {
luminate = {
source = "terraform.example.com/nbs/luminate"
version = "1.0.8"
}
azurerm = {
source = "hashicorp/azurerm"
version = "2.40.0"
}
random = {
source = "hashicorp/random"
}
template = {
source = "hashicorp/template"
}
}
required_version = ">= 0.13"
}
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">=2.38.0, < 3.0.0"
}
luminate = {
source = "terraform.example.com/nbs/luminate"
version = "1.0.8"
}
random = {
source = "hashicorp/random"
version = "3.0.0"
}
null = {
source = "hashicorp/null"
version = "3.0.0"
}
}
required_version = ">= 0.13"
}
My original AWK script looked like this:
/^[[:space:]]{2,2}required_providers/,/^[[:space:]]{2,2}}$/ {
gsub("\"", "")
if ($0 ~ /[[:alpha:]][[:space:]]=[[:space:]]\{/) {
pr = $1
}
if ($0 ~ /version[[:space:]]=[[:space:]]/) {
printf("%s %s\n", pr, $3)
}
}
Which would print out the following:
azurerm > # note this
luminate 1.0.8
azurerm 2.40.0
azurerm >=2.38.0, # note this
luminate 1.0.8
random 3.0.0
null 3.0.0
When people submitted code to the repo the versions line would normally not contain spaces inbetween the " and I would be fine, however this is tending not to be the case lately. So therefore my script messes up on the two lines noted above.
I noted in a book that I've been reading where I can change the Field Separator multiple times in a script (https://www.packtpub.com/product/learning-awk-programming/9781788391030):
Now, to switch between two different FS, we can perform the following:
$ vi fs1.awk
{
if ($1 == "#entry")
{ FS=":"; }
else if ($1 == "#exit")
{ FS=" "; }
else
{ print $2 }
}
I have tried this in my script, but it doesn't work. I can only assume that it's because I'm trying to perform the switch in nested functions?
/^[[:space:]]{2,2}required_providers/,/^[[:space:]]{2,2}}$/ {
if ($0 ~ /[[:alpha:]][[:space:]]=[[:space:]]\{/) {
FS = " "
pr = $1
}
if ($0 ~ /version[[:space:]]=[[:space:]]/) {
FS = "\""
printf("%s %s\n", pr, $2)
}
}
Which outputs like:
azurerm =
luminate =
azurerm =
azurerm =
luminate =
random =
null =
Can anyone suggest a fix/workaround for capturing/printing the output so it looks like:
azurerm > 2.0.0
luminate 1.0.8
azurerm 2.40.0
azurerm >=2.38.0, < 3.0.0
luminate 1.0.8
random 3.0.0
null 3.0.0
A much simpler solution is to just normalize the value you are pulling out. You are using a regex already; just stretch it a little bit further.
/^[[:space:]]{2}required_providers/,/^[[:space:]]{2}}$/ {
gsub("\"", "")
if ($0 ~ /[[:alpha:]][[:space:]]=[[:space:]]\{/) {
pr = $1
}
if ($0 ~ /version[[:space:]]*[<>=]+[[:space:]]*/) {
ver = $0;
sub(/^[[:space:]]*version[[:space:]]*(=[[:space:]]*)?/, "", ver);
print pr, ver
}
}
Tangentially, notice how I relaxed the whitespace requirements, and replaced {2,2} with the equivalent but more succinct {2}.
Changing FS does not have immediate effect, consider that if file.txt content is
1-2-3
4-5-6
then
awk '(NR==1){FS="-"}{print NF}' file.txt
output
1
3
As you can see new FS was applied starting from next line. If you need to split in current line like FS would do consider using split function, for example for same file input as above
awk '{split($0,arr,"-");print arr[1],arr[2],arr[3]}' file.txt
output
1 2 3
4 5 6
(tested in gawk 4.2.1)
With your shown samples only, could you please try following. Written and tested in GNU awk.
awk '
!NF{
found1=found2=0
val=""
}
/required_providers/{
found1=1
next
}
found1 && /^[[:space:]]+[[:alpha:]]+ = {/{
sub(/^ +/,"",$1)
val=$1
found2=1
next
} found2 && /version/{
match($0,/".*"/)
print val,substr($0,RSTART+1,RLENGTH-2)
found2=0
}
' Input_file
Explanation: Adding detailed explanation for above.
awk ' ##Starting awk program from here.
!NF{ ##checking condition if NF is NULL then do following.
found1=found2=0 ##Setting found1 and found2 to 0 here.
val="" ##Nullifying val here.
}
/required_providers/{ ##Checking if line has required_providers then do following.
found1=1 ##Setting found1 to 1 here.
next ##next will skip all further statements from here.
}
found1 && /^[[:space:]]+[[:alpha:]]+ = {/{ ##Checking if found1 is set and line has spaces and alphabets followed by = { then do following.
sub(/^ +/,"",$1) ##Substituting initial spaces with NULL here in first field.
val=$1 ##Setting $1 to val here.
found2=1 ##Setting found2 here.
next ##next will skip all further statements from here.
} found2 && /version/{ ##Checking condition if found2 is set and line has version in it.
match($0,/".*"/) ##Using match to match regex from " to till " here.
print val,substr($0,RSTART+1,RLENGTH-2) ##Printing val and sub string of matched values.
found2=0 ##Setting found2 to 0 here.
}
' Input_file ##Mentioning Input_file name here.

replace name with another keywork in qlikview script

Here i want to ask i have this line in qlivkiew script in that i want if there is "abc" or "def" available then i want to consider these as XYZ and if not available then want to consider as "NONE"
if(if(Filename = '1.xlsx','DR',
if(Filename = '2.xlsx','DR',
if(Filename = '3.xlsx','DRD',
if(Filename = '4.xlsx', 'DRD',
ApplyMap('Segm',Ext.,RGro') = 'abc' or 'def', 'XYZ','None') as In_Flag
how i modified this line according to my requirement
how i do that
any idea about this condition ?
You need to repeat the test to use the or
if(if(Filename = '1.xlsx','DR',
if(Filename = '2.xlsx','DR',
if(Filename = '3.xlsx','DRD',
if(Filename = '4.xlsx', 'DRD',
ApplyMap('Segm',Ext.,RGro') = 'abc' or ApplyMap('Segm',Ext.,RGro') = 'def','XYZ','None') as In_Flag
otherwise match can work
match(ApplyMap('Segm',Ext.,RGro'),'abc','xyz')

Perl string parsing different variation

Experts... I'm creating another question in continuation with my earlier query.... this question is different from earlier request so I thought better to create new thread instead of confusing experts answers.
Below code connects each alias in tnsfile to the database...
1. Is there anyway I can limit each database connection only once and don't allow different alias connecting to the same database again?
I tried using hash but no able to fix this..
use strict;
use warnings;
if /^(([A-Za-z][A-Za-z0-9]*)(\.([A-Za-z][A-Za-z0-9]*))*)(\s|,|=)/
{
{
$hashref->{$1}="";
}
}
Below regex can select each SID value from file but not able to combine with if...
(/\(CONNECT_DATA\s+=\s+\(SID\s+=\s+(\w+\d+?)(\s+)?\)/)
Sample file (tnsfile.txt)
DB1.UK, DB2.UK =
(
(ADDRESS = (PROTOCAL = TCP))
(CONNECT_DATA = (SID = db1))
)
DB1.EU, DB2.CH =
(
(ADDRESS = (PROTOCAL = TCP))
(CONNECT_DATA = (SID = db1))
)
DB3.UK =
(
(ADDRESS = (PROTOCAL = TCP))
(CONNECT_DATA = (SID = db3))
)
DB3.US =
(
(ADDRESS = (PROTOCAL = TCP))
(CONNECT_DATA = (SID = db3))
)
DB4.UK.US, DB4.US =
(
(ADDRESS = (PROTOCAL = TCP))
(CONNECT_DATA = (SID = db4))
)
Expected $hashref value:
DB1.UK
DB3.UK
DB4.UK.US
Are you caching your database handles? It sounds like you are.
If so, you just need to create a new hash that relates SID to database handles. Then you only optionally create a new handle if that SID hasn't already been loaded.
In psuedocode:
my %dbh_by_sid;
while (<DATA>) {
my $sid = ...;
my $dbh = $dbh_by_sid{$sid} ||= DBI->connect(...)
or die "DB connect failed: $DBI::errstr";
# ...
}
This way if that particular SID has already been connected to, it will reuse the same handle.
This is far from a refined solution, and it breaks if the format of your tns file changes dramatically, but you could try something like this:
use strict;
my (%tns, %sid, $tns);
open IN, 'tnsfile.txt' or die;
while (<IN>) {
if (/^([\w.]+)/) {
($tns) = $1;
}
if (/SID *= *([\w.]+)/) {
$tns{$tns} = $1 unless ($sid{$1}++)
}
}
close IN;
print join "\n", keys %tns;

Bash script with regex find/replace to vertically-align assignment operators in file

I have a collection of (jade template) files with properties listed like this:
a.btn(data-ng-class = "{true:'black', false:'blue'}[viewModel.currentDictionaryUid == '<%= full.uid %>']", href = "#<%= viewRoot %>/<%= full.uid %>")
I'm looking for a quick way to possibly convert them to look more like this:
a.btn(data-ng-class = "{true:'black', false:'blue'}[viewModel.currentDictionaryUid == '<%= full.uid %>']"
href = "#<%= viewRoot %>/<%= full.uid %>")
All of the comma seperated properties are now on separate lines, the keys all begin at the same x number of characters from the left, and the equals signs also all being at the same number of x characters from the left.
--- EDIT:
Example test file:
html
body
// HEADER GOES HERE
.header.navbar.navbar-inverse.navbar-fixed-top(style = "z-index:1001;", data-ng-controller = "ControllerWidgetCoreHeader", data-ng-include = "'viewWidgetCoreHeader'")
.page-container.row-fluid(data-ng-class = "{'sidebar-closed':sidebarClosed}")
// LEFT MENU GOES HERE
.page-sidebar.nav-collapse.collapse(data-ng-hide = "quizMode", data-ng-class = "{'in':topBarOpen}", style = "z-index:1000;", data-ng-controller = "ControllerWidgetCoreLeftMenu", data-ng-include = "'viewWidgetCoreLeftMenu'")
.page-content(data-ng-class = "{'page-content-quiz-mode':quizMode}")
// PAGE CONTENT GOES HERE
.container-fluid(data-ng-controller = "ControllerCoreWidgets", data-ng-include = "'viewCoreWidgets'")
.footer(data-ng-show = "false", data-ng-controller = "ControllerWidgetCoreFooter", data-ng-include = "'viewWidgetCoreFooter'")
Error I'm encountering: (Mac OSX 10.8.4)
Casey-Flynns-MacBook-Air:views casey$ sed -i'' 's#,\s\+\([a-z]\+\)\s\+=#\n\t\1 =#g' **/*.jade
sed: 1: "viewsDirectives/viewCol ...": invalid command code v
Also on a single file:
Casey-Flynns-MacBook-Air:views casey$ sed -i'' 's#,\s\+\([a-z]\+\)\s\+=#\n\t\1 =#g' viewCore.jade
sed: 1: "viewCore.jade": invalid command code v
Try doing this :
sed 's#,\s\+\([a-z]\+\)\s\+=#\n\t\1 =#g' **/*.jade
and if it fits your needs, you can use inplace substitution with -i switch :
sed -i 's#,\s\+\([a-z]\+\)\s\+=#\n\t\1 =#g' **/*.jade
And MacOsX version (it treat -i switch the odd way) :
sed -i'' 's#,\s\+\([a-z]\+\)\s\+=#\n\t\1 =#g' **/*.jade
Not sure if this would help but you can try something like:
awk -v RS="," '{ print $0 }' file | column -t | awk '!/=/ {$1=$1}1'
Test:
$ cat file
html
body
// HEADER GOES HERE
.header.navbar.navbar-inverse.navbar-fixed-top(style = "z-index:1001;", data-ng-controller = "ControllerWidgetCoreHeader", data-ng-include = "'viewWidgetCoreHeader'")
.page-container.row-fluid(data-ng-class = "{'sidebar-closed':sidebarClosed}")
// LEFT MENU GOES HERE
.page-sidebar.nav-collapse.collapse(data-ng-hide = "quizMode", data-ng-class = "{'in':topBarOpen}", style = "z-index:1000;", data-ng-controller = "ControllerWidgetCoreLeftMenu", data-ng-include = "'viewWidgetCoreLeftMenu'")
.page-content(data-ng-class = "{'page-content-quiz-mode':quizMode}")
// PAGE CONTENT GOES HERE
.container-fluid(data-ng-controller = "ControllerCoreWidgets", data-ng-include = "'viewCoreWidgets'")
.footer(data-ng-show = "false", data-ng-controller = "ControllerWidgetCoreFooter", data-ng-include = "'viewWidgetCoreFooter'")
$ awk -v RS="," '{ print $0 }' file | column -t | awk '!/=/ {$1=$1}1'
html
body
// HEADER GOES HERE
.header.navbar.navbar-inverse.navbar-fixed-top(style = "z-index:1001;"
data-ng-controller = "ControllerWidgetCoreHeader"
data-ng-include = "'viewWidgetCoreHeader'")
.page-container.row-fluid(data-ng-class = "{'sidebar-closed':sidebarClosed}")
// LEFT MENU GOES HERE
.page-sidebar.nav-collapse.collapse(data-ng-hide = "quizMode"
data-ng-class = "{'in':topBarOpen}"
style = "z-index:1000;"
data-ng-controller = "ControllerWidgetCoreLeftMenu"
data-ng-include = "'viewWidgetCoreLeftMenu'")
.page-content(data-ng-class = "{'page-content-quiz-mode':quizMode}")
// PAGE CONTENT GOES HERE
.container-fluid(data-ng-controller = "ControllerCoreWidgets"
data-ng-include = "'viewCoreWidgets'")
.footer(data-ng-show = "false"
data-ng-controller = "ControllerWidgetCoreFooter"
data-ng-include = "'viewWidgetCoreFooter'")