Grep filter not stop at first match - linux

I am trying to use
grep -o "javascript:add2BasketProd.*?jpg"
to extract string from
javascript:add2BasketProd('xKonfGFJsakj', 'Tattoo-Bubble-Gum-7cm-Bubble-Gum.jpg')Funny-Glasses-and-Teeth-Toy-Candy-TC-747-.jpg
but it would give no output. So I changed the code to the following but the output I get is entire string and not until the first match of jpg.
grep -o "javascript:add2BasketProd.*\?jpg"
My expected output is:
javascript:add2BasketProd('xKonfGFJsakj', 'Tattoo-Bubble-Gum-7cm-Bubble-Gum.jpg
Can anyone suggest a solution?

grep uses POSIX style regular expression which are always greedy. If your grep supports the -P flag, you can use it to enable perl style regex which do support non-greedy matches:
grep -oP "javascript:add2BasketProd.*?jpg"
The GNU grep, which is used on linux, supports -P. The Mac OSX grep does not.

You can use egrep for advanced regex capabilities:
s='javascript:add2BasketProd('xKonfGFJsakj', 'Tattoo-Bubble-Gum-7cm-Bubble-Gum.jpg')Funny-Glasses-and-Teeth-Toy-Candy-TC-747-.jpg'
egrep -o "javascript:add2BasketProd.*?jpg" <<< "$s"
javascript:add2BasketProd(xKonfGFJsakj, Tattoo-Bubble-Gum-7cm-Bubble-Gum.jpg

Related

Finding an exact match in QNX without using grep -w

I'm writing a script that needs to find an exact match in a file that is compatible with QNX and POSIX compliant Linux
more detail:
Im trying to find the user of a process so the original command I wrote was
user=$(ps -aux | awk '{print $1 " " $2}' | grep -w ${process} | awk '{}print $1')
which works perfectly in POSIX compliant Linux
however, QNX isn't totally POSIX compliant and grep -w isn't usable for my target...so I need to find an exact match without grep -w
I think you want to print field 1 if field 2 exactly matches something:
ps -aux | awk -v p=$process '$2==p{print $1}'
-w is not a valid POSIX option for grep, shouldn't be using that for an application that is supposed to be portable between POSIX systems. Could always just ps -p $1 -o user= ? What are you going to do with grep and awk in cases where the user may be the same as the process id?

How to cut the date out of a string in Shell?

I got a list of Strings like this in a .txt file
asdafdgdhjhgk.de/dsafdfdfgfdggfgg - Abgelaufen seit 26.11.2076 14:08 (seit 12345 Tagen)
Now I want to cut the date out of the strings like: 26.11.2076
All this have to happen in a Shell-Script so I through cut or sed would be a good idea but i didn't found an answer in the internet.
You can use GNU grep with -E with extended regEx support using the -E, --extended-regexp flag.
$ grep -Eo "[[:digit:]]{2}.[[:digit:]]{2}.[[:digit:]]{4}" <<< "asdafdgdhjhgk.de/dsafdfdfgfdggfgg - Abgelaufen seit 26.11.2076 14:08 (seit 12345 Tagen)"
26.11.2076
(or) if you want to run it on a file with multiple such strings, do
$ grep -Eo "[[:digit:]]{2}.[[:digit:]]{2}.[[:digit:]]{4}" input-file
If the structure of the logs/lines are similar from start till the date then following could be used:
awk '{print $5}' input
Or
grep -oP '([3][0-1]|[1-2][0-9]|[0][1-9])\.([0][0-9]|[1][0-2])\.[0-9]{4}' input
Note: this may break for month of feb.
When it comes to text parsing, I almost always prefer Perl.
Multiple comma-separated matches per line:
perl -ne '#_=/((?:\d\d\.){2}\d{4})/g and print join(",", #_), "\n"' file
Multiple matches per line joined into a single column:
perl -ne 'while (/((?:\d\d\.){2}\d{4})/g) {print "$&\n";}' file
The first matches:
perl -ne '/((?:\d\d\.){2}\d{4})/ and print "$1\n"' file
If the dates are followed by time, add (?: \d\d:\d\d) to the regular expressions, e.g.
/((?:\d\d\.){2}\d{4})(?: \d\d:\d\d)/
This will make the matches stricter. Note, (?:) is a non-capturing group.
I also like grep's -P option that enables Perl-compatible regular expressions:
grep -o -P '(?:\d\d\.){2}\d{4}' file
But some implementations may not support it:
This is highly experimental and grep -P may warn of unimplemented features.
(the man page for grep).

How to suppress patterns being treated as options in grep

In grep, when I try to find a pattern in the man page, the pattern is treated as the option of grep if it starts with -. For example, I find someone is using uname -r and I wonder what does -r means for uname.
uname --help | grep '-r'
But I got the following error,
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
Seems as if -r is treated as an option for grep.
There are two ways:
If supported by your version, use -- to stop argument processing.
uname --help | grep -- '-r'
Use the -e option to specify the pattern. Since it expects an argument,
grep will not treat the next string as a new option just because it starts with a hyphen.
uname --help | grep -e '-r'
As described in the man page for grep:
-e PATTERN, --regexp=PATTERN
Use PATTERN as the pattern. This can be used to specify multiple search patterns, or to protect a pattern beginning with a hyphen (-). (-e is specified by POSIX.)
uname --help | grep -e -r does what is expected.
Backslash also seems to help:
uname --help | grep "\-r"
uname --help | grep '\-r'

grep with negative pattern

I am looking for a way to grep a file for a specific pattern with negative pattern in it.
I have a log file witch reports units version and I want to see if there is a unit witch report version other then 26.
The closest I could get is :
cat my.log | grep -i -e "version=0x[^2][^6]"
The above return a line contain "version=0x13" but not return a line contain "version=0x23"
Is there a way to tell grep to do so ?
Thanks.
Interpret the pattern as a perl regular expression using the -P switch:
grep -iP 'version=0x(?!26)\d\d' my.log
grep -i "version=0x[0-9]\\+" my.log | grep -iv "version=0x26"

Grep not as a regular expression

I need to search for a PHP variable $someVar. However, Grep thinks that I am trying to run a regex and is complaining:
$ grep -ir "Something Here" * | grep $someVar
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
$ grep -ir "Something Here" * | grep "$someVar"
<<Here it returns all rows with "someVar", not only those with "$someVar">>
I don't see an option for telling grep not to interpret the string as a regex, but to include the $ as just another string character.
Use fgrep (deprecated), grep -F or grep --fixed-strings, to make it treat the pattern as a list of fixed strings, instead of a regex.
For reference, the documentation mentions (excerpts):
-F --fixed-strings Interpret the pattern as a list of fixed
strings (instead of regular expressions), separated by newlines, any
of which is to be matched. (-F is specified by POSIX.)
fgrep is the same as grep -F. Direct invocation as fgrep is
deprecated, but is provided to allow historical applications that rely
on them to run unmodified.
For the complete reference, check:
https://www.gnu.org/savannah-checkouts/gnu/grep/manual/grep.html
grep -F is a standard way to tell grep to interpret argument as a fixed string, not a pattern.
You have to tell grep you use a fixed-string, instead of a pattern, using '-F' :
grep -ir "Something Here" * | grep -F \$somevar
In this question, the main issue is not about grep interpreting $ as a regex. It's about the shell substituting $someVar with the value of the environment variable someVar, likely the empty string.
So in the first example, it's like calling grep without any argument, and that's why it gives you a usage output. The second example should not return all rows containing someVar but all lines, because the empty string is in all lines.
To tell the shell to not substitute, you have to use '$someVar' or \$someVar. Then you'll have to deal with the grep interpretation of the $ character, hence the grep -F option given in many other answers.
So one valid answer would be:
grep -ir "Something Here" * | grep '$someVar'
+1 for the -F option, it shall be the accepted answer.
Also, I had a "strange" behaviour while searching for the -I.. pattern in my files, as the -I was considered as an option of grep ; to avoid such kind of errors, we can explicitly specify the end of the arguments of the command using --.
Example:
grep -HnrF -- <pattern> <files>
Hope that'll help someone.
Escape the $ by putting a \ in front of it.

Resources