I try to grep the (write access) password from .my.cnf, but I didnt get it yet.
The .my.cnf looks like this:
# longer
# comment text
[clientreadonly]
password=pass1 # comment
port=3306
user=test_ro
socket=/var/lib/mysql/mysql.sock
[client]
password=pass2 # comment
port=3306
user=test
socket=/var/lib/mysql/mysql.sock
and I want to grep pass2. and the code shouldnt be too verbose of course. I ended up with
grep 'password=' ~/.my.cnf | sed -e 's/password=//
but thath actually leaves the #comment behind the pass2 and I dont want to replace the whole comment (because its long in the original and stupid to just replace it). So I would need a regex to somehow get the pass2 only.
The main target is, to grep the password so I can easily use it in a shell command line
$ awk -F'[= ]' '/^password=/ && p !~ /clientreadonly/{print $2} {p=$0}' ~/.my.cnf
pass2
-F'[= ]' use space or = as field separator
/^password=/ && p !~ /clientreadonly/ if line starts with password= and previous line doesn't contain clientreadonly
print $2 print the second field
p=$0 save the previous line in p variable
You can modify little bit like the following -
grep 'password=' ~/.my.cnf | sed -e 's/password=//' -e 's/ # comment//'
or other way -
grep 'password=' ~/.my.cnf | cut -d' ' -f1 | cut -d'=' -f2
Using perl:
perl -00 -ane '/\[client\].password=(\S+)/s && print $1' < ~/.my.cnf
Output:
pass2
Related
I have the following code:
url='https://github.com/Project/name-app.git'
echo $url
I have to get this back to me, i.e. the name of the project regardless of the owner of the project.
Result:
name-app
You can use string manipulation in Bash:
url='https://github.com/Project/name-app.git'
url="${url##*/}" # Remove all up to and including last /
url="${url%.*}" # Remove up to the . (including) from the right
echo "$url"
# => name-app
See the online Bash demo.
Another approach with awk:
url='https://github.com/Project/name-app.git'
url=$(awk -F/ '{sub(/\..*/,"",$NF); print $NF}' <<< "$url")
echo "$url"
See this online demo. Here, the field delimiter is set to /, the last field value is taken and all after first . is removed from it (together with the .), and that result is returned.
You can use grep regexp:
url='https://github.com/Project/name-app.git'
echo $url | grep -oP ".*/\K[^\.]*"
You can use bash expansion:
url='https://github.com/Project/name-app.git'
mytemp=${url##*/}
echo ${mytemp%.*}
1st solution: With your shown samples please try following awk code.
echo $url | awk -F'\\.|/' '{print $(NF-1)}'
OR to make sure last value is always ending with .git try a bit tweak in above code:
echo "$url" | awk -F'\\.|/' '$NF=="git"{print $(NF-1)}'
2nd solution: Using sed try following:
echo "$url" | sed 's/.*\///;s/\..*//'
# my prefered solution
url='https://github.com/Project/name-app.git'
basename $url .git
> name-app
# others
sed 's/\(.*\/\)\([^\/]*\)\.\(\w*\)$/\2/g' <<<$url
1.https://github.com/Project/
2.name-app
#
awk -F"[/.]" '{print $(NF-1)}' <<<$url
awk -F"[/.]" '{print $6}' <<<$url
tr '/.' '\n' <<<$url|tail -2|grep -v git
I am trying to print out the contents of a TNS entry from the tnsnames.ora file to make sure it is correct from an Oracle RAC environment.
So if I do something like:
grep -A 4 "mydb.mydomain.com" $ORACLE_HOME/network/admin/tnsnames.ora
I will get back:
mydb.mydomain.com =
(DESCRIPTION =
(ADDRESS =
(PROTOCOL = TCP)(HOST = myhost.mydomain.com)(PORT = 1521))
(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME=mydb)))
Which is what I want. Now I have an environment variable being set for the JDBC connection string by an external program when the shell script gets called like:
export $DB_URL=#myhost.mydomain.com:1521/mydb
So I need to get TNS alias mydb.mydomain.com out of the above string. I'm not sure how to do multiple matches and reorder the matches with regex and need some help.
grep #.+: $DB_URL
I assume will get the
#myhost.mydomain.com:
but I'm looking for
mydb.mydomain.com
So I'm stuck at this part. How do I get the TNS alias and then pipe/combine it with the initial grep to display the text for the TNS entry?
Thanks
update:
#mklement0 #Walter A - I tried your ways but they are not exactly what I was looking for.
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 }'
All these methods get me back: myhost.mydomain.com
What I am looking for is actually: mydb.mydomain.com
Note:
- For brevity, the commands below use bash/ksh/zsh here-string syntax to send strings to stdin (<<<"$var"). If your shell doesn't support this, use printf %s "$var" | ... instead.
The following awk command will extract the desired string (mydb.mydomain.com) from $DB_URL (#myhost.mydomain.com:1521/mydb):
awk -F '[#:/]' '{ sub("^[^.]+", "", $2); print $4 $2 }' <<<"$DB_URL"
-F'[#:/]' tells awk to split the input into fields by either # or : or /. With your input, this means that the field of interest are part of the second field ($2) and the fourth field ($4). The sub() call removes the first .-based component from $2, and the print call pieces together the result.
To put it all together:
domain=$(awk -F '[#:/]' '{ sub("^[^.]+", "", $2); print $4 $2 }' <<<"$DB_URL")
grep -F -A 4 "$domain" "$ORACLE_HOME/network/admin/tnsnames.ora"
You don't strictly need intermediate variable $domain, but I've added it for clarity.
Note how -F was added to grep to specify that the search term should be treated as a literal, so that characters such as . aren't treated as regex metacharacters.
Alternatively, for more robust matching, use a regex that is anchored to the start of the line with ^, and \-escape the . chars (using shell parameter expansion) to ensure their treatment as literals:
grep -A 4 "^${domain//./\.}" "$ORACLE_HOME/network/admin/tnsnames.ora"
You can get a part of a string with
# 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%:*}"
I had skipped the alternative awk, that was given by #mklement0 already:
echo "#myhost.mydomain.com:1521/mydb" | awk -F'[#:]' '{ print $2 }'
The awk solution is straight-forward, when you want to use the same approach without awk you can do something like
echo "#myhost.mydomain.com:1521/mydb" | tr "#:" "\t" | cut -f2
or the ugly
echo "#myhost.mydomain.com:1521/mydb" | (IFS='#:' read -r _ url _; echo "$url")
What is happening here?
After introducing the new IFS I want to take the second word of the input. The first and third word(s) are caught in the dummy var's _ (you could have named them dummyvar1 and dummyvar2). The pipe | creates a subprocess, so you need ()to hold reading and displaying the var url in the same process.
I want to find the string in that is placed with in the brackets. How do I use sed to pull the string?
# cat /sys/block/sdb/queue/scheduler
noop anticipatory deadline [cfq]
I'm not getting the exact result
# cat /sys/block/sdb/queue/scheduler | sed 's/\[*\]//'
noop anticipatory deadline [cfq
I'm expecting an output
cfq
It can be easier with grep, if it happens to be changing the position in which the text in between brackets is located:
$ grep -Po '(?<=\[)[^]]*' file
cfq
This is look-behind: whenever you find a string [, start fetching all the characters up to a ].
See another example:
$ cat a
noop anticipatory deadline [cfq]
hello this [is something] we want to [enclose] yeah
$ grep -Po '(?<=\[)[^]]*' a
cfq
is something
enclose
You can also use awk for this, in case it is always in the same position:
$ awk -F[][] '{print $2}' file
cfq
It is setting the field separators as [ and ]. And from that, prints the second one.
And with sed:
$ sed 's/[^[]*\[\([^]]*\).*/\1/g' file
cfq
It is a bit messy, but basically it is looking from the block of text in between [] and prints it back.
I found one possible solution-
cut -d "[" -f2 | cut -d "]" -f1
so the exact solution is
# cat /sys/block/sdb/queue/scheduler | cut -d "[" -f2 | cut -d "]" -f1
Another potential solution is awk:
s='noop anticipatory deadline [cfq]'
awk -F'[][]' '{print $2}' <<< "$s"
cfq
Another way by gnu grep :
grep -Po "\[\K[^]]*" file
with pure shell:
while read line; do [[ "$line" =~ \[([^]]*)\] ]] && echo "${BASH_REMATCH[1]}"; done < file
Another awk
echo 'noop anticipatory deadline [cfq]' | awk '{gsub(/.*\[|\].*/,x)}8'
cfq
perl -lne 'print $1 if(/\[([^\]]*)\]/)'
Tested here
I have a file in linux with similar entries as below
dn: CN=HP_NetworkSupport,OU=groups,DC=HDFCSLDM,DC=COM
dn: CN=Review users,OU=groups,DC=HDFCSLDM,DC=COM
I would like to extract only the CN information, till the first ,
for ex:
> HP_NetworkSupport
> Review users
in the above case to another file.
What would be command for doing the same.
This is one way with lookahead:
grep -Po '(?<=CN=)[^,]*' file > new_file
It gets all text from CN= (not included) until it finds a comma ,. The idea of [^,]* is to fetch any character that is not a comma.
Test
$ grep -Po '(?<=CN=)[^,]*' file
HP_NetworkSupport
Review users
Using awk
awk -F"=|," '{print $2}' file
HP_NetworkSupport
Review users
or
awk -F[=,] '{print $2}' file
HP_NetworkSupport
Review users
Set the delimiter to , or =, then print second field.
To handel field with comma within, you should use a parser for LDAP, but this should work.
echo file
dn: CN=HP_NetworkSupport,OU=groups,DC=HDFCSLDM,DC=COM
dn: CN="Review, users",OU=groups,DC=HDFCSLDM,DC=COM
awk -F"CN=|,OU" '{print $2}' file
HP_NetworkSupport
Review, users
Using sed:
$ sed -r 's/.*CN=([^,]*),.*/\1/' inputfile
HP_NetworkSupport
Review users
perl -lne 'print $1 if(/CN=([^\,]*),/)' your_file
Tested Below:
> cat temp
dn: CN=HP_NetworkSupport,OU=groups,DC=HDFCSLDM,DC=COM
dn: CN=Review users,OU=groups,DC=HDFCSLDM,DC=COM
> perl -lne 'print $1 if(/CN=([^\,]*),/)' temp
HP_NetworkSupport
Review users
>
Pipe it through this command:
sed -E "s/.*CN=(.+?),OU=.*/\\1/g"
I have html page with many lines and one of the line is:
var premium_download_link = 'http://www.someurl.com/';
how can I find that line inside html page and extract http://www.someurl.com from the line?
echo "var premium_download_link = 'http://www.someurl.com/'" | awk '{print substr ($4,2,23)}'
Using sed:
sed -n -e "s/.*var premium_download_link = '\([^']*\)';.*/\1/p"
The -n flag suppresses printing unless we explicitly print using p. Thus only matched (then substituted) lines are printed.
EDIT (based on OP comment):
To get this in a shell variable you might want something like:
url=$(wget -qO - "http://originalurl.com/" | sed -n -e "s/.*var premium_download_link = '\([^']*\)';.*/\1/p")
This fetches the page and runs it through sed. The output should be the url, which gets stored in a variable named url.
With awk :
awk -F "'" '{ for (f=1; f<=(NF-1)/2; f++) print $(f*2) }' $1
-F "'" define the quote ' as the separator for given input.
With awk you can extract specific field values by defining the field separator variable.
For instance, the following should work -
$ echo "var premium_download_link = 'http://www.someurl.com/';" |
awk -F"'" '{ print $2 }'
http://www.someurl.com/
However, your html file may have other content. So you can add a regex in front of the script to ensure that it runs only when the specific line is encountered.
For example -
awk -F"'" '/premium_download_link/{ print $2 }'
grep -Po "(?<=premium_download_link = ')[^']+"