How to grep at least one character and double slash - grep

I have a .gnmap file which contains rows like the following:
Host: x.x.x.x () Ports: PORT/open/tcp//PROTOCOL//SERVICE/
I'd like to grep for "/open/tcp//at_least_one_character//at_least_one_character/"
I tried to use grep "/open/tcp//[a-zA-Z]//[a-zA-Z]//", but it does not return anything.
How can I correct the grep above?
Thank you.

Your regexp matches only one character after the //
To match at least one character use +. It tells grep to mach one or more occurrence of the previous character or character class.
grep -E "/open/tcp//[a-zA-Z]+//[a-zA-Z]+/"
-E indicates grep to use extended regular expression. You can have a similar behaviour without the -E option, but you need to backslash the + to give it a special meaning.
grep "/open/tcp//[a-zA-Z]\+//[a-zA-Z]\+/"

Related

grep 3rd keyword from a string seperated by '-'

My hostname details are as below after showing command of hostname in linux
my-host-test-db-10001.dns.biz.xyz.com
my-host-test2-db-10002.dns.biz.xyz.com
my-host-test3-db-10003.dns.biz.xyz.com
I want to fetch the 3rd string from these above (test/test2/test3). how can I achieve it?
In addition to the simpler solution using cut, you can use more flexible grep:
hostname | grep -Po '^[^-]+-[^-]+-\K[^-]+'
For example:
grep -Po '^[^-]+-[^-]+-\K[^-]+' <<< 'my-host-test2-db-10002.dns.biz.xyz.com'
Output:
test2
Here, GNU grep uses the following options:
-P : Use Perl regexes.
-o : Print the matches only (1 match per line), not the entire lines.
\K : Cause the regex engine to "keep" everything it had matched prior to the \K and not include it in the match. Specifically, ignore the preceding part of the regex when printing the match.
SEE ALSO:
perlre - Perl regular expressions

How to include optional space in Grep statement

I have some log files that I'm grepping through which contain entries in the following form
foo($abc) - sometext
foo ($xyz) - moretext
baz($qux) - moartext
I'm looking to use grep that would output the first two lines as matches, i.e.
foo($abc)
foo ($xyz)
I've tried the following grep statement
grep 'foo(\$' log.txt
which outputs the first match, but I tried to include an optional space, and neither return:
grep 'foo\s?(\$' log.txt
I'm using the optional space incorrectly, but I'm unsure how
You are using a POSIX BRE regex and foo\s?(\$ matches foo, a whitespace, a literal ?, a literal ( and a literal $.
You can use
grep -E 'foo\s?\(\$' log.txt
Here, -E makes the pattern POSIX ERE, and thus it now matches foo, then an optional whitespace, and a ($ substring.
See an online demo:
s='foo($abc) - sometext
foo ($xyz) - moretext
baz($qux) - moartext'
grep -E 'foo\s?\(\$' <<< "$s"
Output:
foo($abc) - sometext
foo ($xyz) - moretext
You may still use a more universal syntax like
grep 'foo[[:space:]]\{0,1\}(\$' log.txt
It is a POSIX BRE regex matching foo, one or zero whitespaces, and then ($ substring.
You can either change the query slightly and use * instead of ?:
grep 'foo *(\$' log.txt
or use a literal whitespace and escape ?:
grep 'foo \?(\$' log.txt
Both solutions would work with GNU, busybox and FreeBSD grep.

Search a string which contains backslash using Grep command

In the tail output i have following string...Using grep command how can i search for the string "contentState\":\"STOPPED\". I have to search for the whole string "contentState\":\"STOPPED\" rather
than searching for STOPPED or contentState only.
I tried following command: But it is not working.
grep -e ""contentState\":\"STOPPED\" /opt/logs/out.log | tail -1
{\"eventType\":\"appAction\",\"action\":\"CONTENT_STATE_CHANGE\",\"evt\":{\"contentState\":\"STOPPED\"}}}
To search for "contentState\":\"STOPPED\", you need to (a) put the whole string in single-quotes to protect it, and (b) escape (double) the backslashes. Thus:
grep -e '"contentState\\":\\"STOPPED\\"' /opt/logs/out.log
Without the protection provided the outer single-quotes, the unescaped double-quotes would be subject to the shell's quote removal and grep would never see them.
Example
Consider this test file:
$ cat log
good "contentState\":\"STOPPED\"
bad contentState\":\"STOPPED\"
bad "contentState\":\"STOPPED"
Let's run our command:
$ grep -e '"contentState\\":\\"STOPPED\\"' log
good "contentState\":\"STOPPED\"
As we can see, the good line is returned and only the good line.

grep exact match in colon delimited string

I am trying to extract the version from a colon delimited list. The value I want is for foo, however there is another value in the list called foo-bar causing both values to return. This is what I am doing:
LIST="foo:1.0.0
foo-bar:1.0.1"
VERSION=$(echo "${LIST}" | grep "\bfoo\b" | cut -s -d':' -f2)
echo -e "VERSION: ${VERSION}"
Output:
VERSION: 1.0.0
1.0.1
NOTE: Sometimes LIST will look like the following, which should result in version being empty (this is expected).
LIST="foo
foo-bar:1.0.1"
You may use a PCRE regex enabled with -P option and use a (?!-) negative lookahead that will fail the match in case there is a - after a whole word foo:
grep -P "\bfoo\b(?!-)"
See online demo
This regex should extract any number and optional dots at the end of each line. If the line ends with a colon, then it won't match.
grep -oE '(([[:digit:]]+[.]*)+)$

grep "?" does not match valid matches

I want to match tags in files (with optional brackets) ... easy one would think ... the regex is something like ^\[?MyTag\]?. But ... Grep doesn't like it. None of the lines that would be valid matches are actually matched.
The interesting part is: if I replace the ? with a * (so zero to infinite matches, not zero or one) it matches everything like it should, but really that would mean the feature is broken and I don't believe that.
Any input?
Using grep (GNU grep) 2.22 on Windows.
PS: so grep is like this ...
grep -e "^\[?MyTag\]?" file.txt
and my test file is like this
[MyTag] hello
NotMyTag ugly
[NotMyTag] dumb
MyTag world
which obviously should result in 1st and 4th line showing but shows nothing.
First off, ? is not supported in vanilla grep, so you need to use the -E flag to enable extended regex. You can easily verify this by running grep '?' <<< 'a' and grep -E '?' <<< 'a'. Only the latter will match. -e just explicitly indicates what your regex is. It is not the same as -E.
Your initial command works fine if you change the -e to upper case:
grep -E '^\[?MyTag\]?'
Example:
$ grep -E '^\[?MyTag\]?' <<< '[MyTag] hello
> NotMyTag ugly
> [NotMyTag] dumb
> MyTag world'
Output:
[MyTag] hello
MyTag world
Credit goes to the answers of this question on SuperUser.
? is not part of the basic regular expressions, which grep supports. GNU grep supports them as an extension, but you have to escape them:
$ grep '^\[\?MyTag\]\?' file.txt
[MyTag] hello
MyTag world
Or, as pointed out, use grep -E to enable extended regular expressions.
For GNU grep, the only difference between grep and grep -E, i.e., using basic and extended regular expressions, is what you have to escape and what not.
Basic regular expressions
Capture groups and quantifying have to be escaped: \( \) and \{ \}
Zero or one (?), one or more (+) and alternation (|) are not part of BRE, but supported by GNU grep as an extension (but need to be escaped: \? \+ \|)
Extended regular expressions
Capture groups and quantifying don't have to be escaped: ( ) and { }
?, + and | are supported and don't need be be escaped

Resources