Can grep delete context, but not a full line? - regex

I am removing keys from a config file by the following command:
cat showrunningconfig.txt | grep -v '[ \t\r\n\v\f]*[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]'
This removes the whole line.
But I want to remove only the relevant patterns.
grep has the -o option, which shows only the relevant pattern and not the whole line.
But the -o option is not working in combination with -v
Any idea?
Thanks a lot!

You should use sed when you have a partial pattern to remove from a string.
sed -i 's/[[:space:]]*[[:xdigit:]]\{8\}//g' showrunningconfig.txt
See the online demo
s="Text A1f4E3D4 and more text"
sed 's/[[:space:]]*[[:xdigit:]]\{8\}//g' <<< "$s"
# => Text and more text
Details
-i - in-place replacement (GNU sed option)
s/[[:space:]]*[[:xdigit:]]\{8\}//g:
s - substitute command
[[:space:]]* - 0+ whitespaces
[[:xdigit:]]\{8\} - eight A-F, a-f and 0-9 chars.

Related

Find last word in path and remove brackets with regex using bash

I have done lots of searching on SO and google.
I am using a regex tester like Regex 101.
The test string is [../../dvl/namespaces/my-namespace-1/notterminating]
The regex I am using is .*\/([^\/]*)[\[\]']+.
What I am trying to do (returns empty):
$ param="[../../dvl/namespaces/my-namespace-1/notterminating]"
$ echo $param | grep ".*\/([^\/]*)[\[\]']+"
I have tried different options with grep by adding different flags like -o, -e, etc. I have tried "${param}.*\/([^\/]*)[\[\]']+". However, I have been unsuccessful at getting bash to recognize my regex.
You may use sed:
sed -n "s#.*/\([^]['/]*\).*#\1#p" <<< "$param"
See an online demo
Details
.* - matches 0+ chars
/ - / char
\([^]['/]*\) - Group 1: any 0+ chars other than ], [, ' and /
.* - any 0+ chars.
This way, the whole string is replaced with the Group 1 value, and only that value remains as -n suppresses default line output and p prints the result.
Without using any external tool you can do this in pure bash with IFS:
IFS='/\[\]' read -ra arr <<< "$param" && echo "${arr[-1]}"
notterminating
Otherwise you may use this simple sed:
sed 's~.*/~~' <<< "${param//[]]}"
notterminating
Or by using awk:
awk -F '[][/]' '{print $(NF-1)}' <<< "$param"
notterminating
Using sed:
echo "$param" |sed -r -n 's,.*\/(.*)\],\1,p'
output:
notterminating

Extract version using grep/regex in bash

I have a file that has a line stating
version = "12.0.08-SNAPSHOT"
The word version and quoted strings can occur on multiple lines in that file.
I am looking for a single line bash statement that can output the following string:
12.0.08-SNAPSHOT
The version can have RELEASE tag too instead of SNAPSHOT.
So to summarize, given
version = "12.0.08-SNAPSHOT"
expected output: 12.0.08-SNAPSHOT
And given
version = "12.0.08-RELEASE"
expected output: 12.0.08-RELEASE
The following command prints strings enquoted in version = "...":
grep -Po '\bversion\s*=\s*"\K.*?(?=")' yourFile
-P enables perl regexes, which allow us to use features like \K and so on.
-o only prints matched parts instead of the whole lines.
\b ensures that version starts at a word boundary and we do not match things like abcversion.
\s stands for any kind of whitespace.
\K lets grep forget, that it matched the part before \K. The forgotten part will not be printed.
.*? matches as few chararacters as possible (the matching part will be printed) ...
(?=") ... until we see a ", which won't be included in the match either (this is called a lookahead).
Not all grep implementations support the -P option. Alternatively, you can use perl, as described in this answer:
perl -nle 'print $& if m{\bversion\s*=\s*"\K.*?(?=")}' yourFile
Seems like a job for cut:
$ echo 'version = "12.0.08-SNAPSHOT"' | cut -d'"' -f2
12.0.08-SNAPSHOT
$ echo 'version = "12.0.08-RELEASE"' | cut -d'"' -f2
12.0.08-RELEASE
Portable solution:
$ echo 'version = "12.0.08-RELEASE"' |sed -E 's/.*"(.*)"/\1/g'
12.0.08-RELEASE
or even:
$ perl -pe 's/.*"(.*)"/\1/g'.
$ awk -F"\"" '{print $2}'

How to use sed to remove part of file path

I have lines like these
my_list=cloning/cloning-1.7.jar,commons/commons-lang-2.5.jar
my_lib_list=antlr/antlr-1.0.jar,aopa/aopa-1.0.jar
and I need to remove the part before '/' like this:
my_list=cloning-1.7.jar,commons-lang-2.5.jar
my_lib_list=antlr-1.0.jar,aopa-1.0.jar
I tried this
sed -i -e "s/(?<=\/).*?(\.jar)//g"
Nothing happens. Regex seems to be right (might need to be inverted), but atleast something should change in the file, right?
Your pattern - (?<=\/).*?(\.jar) - contains a lookbehind ((?<=...)) and lazy matching quantifier (*?). Neither are supported by sed.
You can use
sed -E 's/[[:alnum:]]+\///g'
See the IDEONE demo
Pattern details:
[[:alnum:]]+ - 1 or more alphanumeric symbols
\/ - a literal /
You can do:
sed -r 's#^([^=]+=)[^/]+/([^,]+,)[^/]+/(.*)#\1\2\3#'
Example:
$ sed -r 's#^([^=]+=)[^/]+/([^,]+,)[^/]+/(.*)#\1\2\3#' <<<'my_list=cloning/cloning-1.7.jar,commons/commons-lang-2.5.jar'
my_list=cloning-1.7.jar,commons-lang-2.5.jar
$ sed -r 's#^([^=]+=)[^/]+/([^,]+,)[^/]+/(.*)#\1\2\3#' <<<'my_lib_list=antlr/antlr-1.0.jar,aopa/aopa-1.0.jar'
my_lib_list=antlr-1.0.jar,aopa-1.0.jar

Extract few matching strings from matching lines in file using sed

I have a file with strings similar to this:
abcd u'current_count': u'2', u'total_count': u'3', u'order_id': u'90'
I have to find current_count and total_count for each line of file. I am trying below command but its not working. Please help.
grep current_count file | sed "s/.*\('current_count': u'\d+'\).*/\1/"
It is outputting the whole line but I want something like this:
'current_count': u'3', 'total_count': u'3'
It's printing the whole line because the pattern in the s command doesn't match, so no substitution happens.
sed regexes don't support \d for digits, or x+ for xx*. GNU sed has a -r option to enable extended-regex support so + will be a meta-character, but \d still doesn't work. GNU sed also allows \+ as a meta-character in basic regex mode, but that's not POSIX standard.
So anyway, this will work:
echo -e "foo\nabcd u'current_count': u'2', u'total_count': u'3', u'order_id': u'90'" |
sed -nr "s/.*('current_count': u'[0-9]+').*/\1/p"
# output: 'current_count': u'2'
Notice that I skip the grep by using sed -n s///p. I could also have used /current_count/ as an address:
sed -r -e '/current_count/!d' -e "s/.*('current_count': u'[0-9]+').*/\1/"
Or with just grep printing only the matching part of the pattern, instead of the whole line:
grep -E -o "'current_count': u'[[:digit:]]+'
(or egrep instead of grep -E). I forget if grep -o is POSIX-required behaviour.
For me this looks like some sort of serialized Python data. Basically I would try to find out the origin of that data and parse it properly.
However, while being hackish, sed can also being used here:
sed "s/.*current_count': [a-z]'\([0-9]\+\).*/\1/" input.txt
sed "s/.*total_count': [a-z]'\([0-9]\+\).*/\1/" input.txt

regex match specific pattern

I have
[root#centos64 ~]# cat /tmp/out
[
"i-b7a82af5",
"i-9d78f4df",
"i-92ea58d0",
"i-fa4acab8"
]
I would like to pipe though sed or grep to match the format "x-xxxxxxxx" i.e. a mix of a-z 0-9 always in 1-[8 chars length], and omit everything else
[root#centos64 ~]# cat /tmp/out| sed s/x-xxxxxxxx/
i-b7a82af5
i-9d78f4df
i-92ea58d0
i-fa4acab8
I know this is basic, but I can only find examples of text substitution.
grep -Eo '[a-z0-9]-[a-z0-9]{8}' file
The -E option makes it recognize extended regular expressions, so it can use {8} to match 8 repetitions.
The -o option makes it only print the part of the line that matches the regexp.
Why not just print whatever's between the quotes:
$ sed -n 's/[^"]*"\([^"]*\).*/\1/p' file
i-b7a82af5
i-9d78f4df
i-92ea58d0
i-fa4acab8
$ awk -F\" 'NF>1{print $2}' file
i-b7a82af5
i-9d78f4df
i-92ea58d0
i-fa4acab8
Through GNU sed,
$ sed -nr 's/.*([a-z0-9]-[a-z0-9]{8}).*/\1/p' file
i-b7a82af5
i-9d78f4df
i-92ea58d0
i-fa4acab8
I think this is all you need: [0-9a-zA-Z]-[0-9a-zA-Z]{8}. Try it out here.
This should work ^[a-z0-9]-[a-zA-Z0-9]{8}$