Often times I have to do so commandline thing where I pipe to grep and want matches for two different expressions. ( An OR match A OR B. )
For example I want to grep the output of generate_out for either foo[0-9]+ or bar[0-9]+. I of course could just execute twice:
generate_out| grep "foo[0-9]+"
generate_out| grep "bar[0-9]+"
but often generate_out is expensive and I would rather not want to run it twice ( or store it's output ). Rather I would like to just use one expression:
generate_out| grep "foo[0-9]+ OR bar[0-9]+"
of course this will not work but I would like the equivalent expression which will.
use grep's -e option to specify multiple patterns that are "OR'ed":
$ seq 15 | grep -e 5 -e 3
3
5
13
15
Use an alternation in your regex:
generate_out | grep -E '(foo|bar)[0-9]+'
The use of -E enables ERE features, of this which is one. (By default, grep only supports BRE; some implementations of BRE -- such as GNU's -- may have special syntax for enabling ERE features; in the GNU case, \| in BRE is equivalent to | in ERE; however, it's not portable to rely on such extensions instead of just turning on ERE properly).
egrep is a backwards-compatibility synonym for grep -E; however, only the latter is specified as a requirement by POSIX.
Use awk for simplicity:
generate_out| awk '/foo[0-9]+/ || /bar[0-9]+/'
which of course could be simplified in this particular case to:
generate_out| awk '/(foo|bar)[0-9]+/'
but in general you want to use awk for simple, consistent ORs and ANDs of regexps:
cmd | grep -E 'foo.*bar|bar.*foo'
cmd | awk '/foo/ && /bar/'
cmd | grep 'foo' | grep -v 'bar'
cmd | awk '/foo/ && !/bar/'
cmd | grep -E 'foo|bar'
cmd | awk '/foo/ || /bar/' (or awk '/foo|bar/')
cmd | grep -E 'foo|bar' | grep -E -v 'foo.*bar|bar.*foo'
cmd | awk '(/foo/ && !/bar/) || (/bar/ && !/foo/)'
Related
I can't see what I'm missing in my grep command, can you?
http://regexr.com/5shri
echo "2021-05-09 15:38:56.888 T:1899877296 NOTICE: VideoPlayer::OpenFile:plugin://plugin.video.arteplussept/play/SHOW/069083-002-A" | grep -oE "\w+(?=\/play)/g" -
Expect: arteplussept
You need to
Use the PCRE regex engine, with -P option, not -E (which stands for POSIX ERE)
Remove /g, grep -o extracts all matches and there is no need to "embed" this modifier into the pattern
There is no need to escape /
So, you can just use
grep -oP '\w+(?=/play)'
I have this a file.txt with one line, whose content is
/app/jdk/java/bin/java -server -Xms3g -Xmx3g -XX:MaxPermSize=256m -Dweblogic.Name=O2pPod8_mapp_msrv1_1 -Djava.security.policy=/app/Oracle/Middleware/Oracle_Home/wlserver/server/lib/weblogic.policy -Djava.security.egd=file:/dev/./urandom -Dweblogic.ProductionModeEnabled=true -Dweblogic.system.BootIdentityFile=/app/Oracle/Middleware/Oracle_Home/user_projects/domains/O2pPod8_domain/servers/O2pPod8_mapp_msrv1_1/data/nodemanager/boot.properties -Dweblogic.nodemanager.ServiceEnabled=true -Dweblogic.nmservice.RotationEnabled=true -Dweblogic.security.SSL.ignoreHostnameVerification=false -Dweblogic.ReverseDNSAllowed=false -Xms8192m -Xmx8192m -XX:MaxPermSize=2048m -XX:NewSize=1300m -XX:MaxNewSize=1300m -XX:SurvivorRatio=4 -XX:TargetSurvivorRatio=90 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled
and when I do
cat file.txt | grep -io "Xms.*" | awk '{FS" "; print $1} ' | cut -d "s" -f2
output:
3g
why is grep not reading the second occurrence, i.e. I expect 3g and 8192m.
Infact, how do I print only 8192m in this case?
Your regex just says "find Xms followed by anything repeated 0 to n times". That returns the rest of the row from Xms onward.
What you actually want is something like "find Xms followed by anything until there's a whitespace repeated 0 to n times".
grep -io "Xms[^ ]*" file.txt | awk '{FS" "; print $1} ' | cut -d "s" -f2
In [^ ] the ^ means "not"
I'm not really sure what you are trying to achieve here but if you want the endings of all space-separated strings starting with -Xms, using bare awk is:
$ awk -v RS=" " '/^-Xms/{print substr($0,5)}' file
3g
8192m
Explained:
$ awk -v RS=" " ' # space separated records
/^-Xms/ { # strings starting with -Xms
print substr($0,5) # print starting from 5th position
}' file
If you wanted something else (word repeated in the title puzzles me a bit), please update the question with more detailed requirements.
Edit: I just noticed how do I print only 8192m in this case (that's the repeated maybe). Let's add a counter c and not print the first instance:
$ awk -v RS=" " '/^-Xms/&&++c>1{print substr($0,5)}' file
8192m
You could use grep -io "Xms[0-9]*[a-zA-Z]" instead of grep -io "Xms.*" to match a sequence of digits followed by a single character instead the entire line within a single group:
cat file.txt | grep -io "Xms[0-9]*[a-zA-Z]" | awk '{FS" "; print $1} ' | cut -d "s" -f2
Hope this helps!
The .* in your regexp is matching the rest of the line, you need [^ ]* instead. Look:
$ grep -o 'Xms.*' file
Xms3g -Xmx3g -XX:MaxPermSize=256m -Dweblogic.Name=O2pPod8_mapp_msrv1_1 -Djava.security.policy=/app/Oracle/Middleware/Oracle_Home/wlserver/server/lib/weblogic.policy -Djava.security.egd=file:/dev/./urandom -Dweblogic.ProductionModeEnabled=true -Dweblogic.system.BootIdentityFile=/app/Oracle/Middleware/Oracle_Home/user_projects/domains/O2pPod8_domain/servers/O2pPod8_mapp_msrv1_1/data/nodemanager/boot.properties -Dweblogic.nodemanager.ServiceEnabled=true -Dweblogic.nmservice.RotationEnabled=true -Dweblogic.security.SSL.ignoreHostnameVerification=false -Dweblogic.ReverseDNSAllowed=false -Xms8192m -Xmx8192m -XX:MaxPermSize=2048m -XX:NewSize=1300m -XX:MaxNewSize=1300m -XX:SurvivorRatio=4 -XX:TargetSurvivorRatio=90 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled
$ grep -o 'Xms[^ ]*' file
Xms3g
Xms8192m
$ grep -o 'Xms[^ ]*' file | cut -d's' -f2
3g
8192m
$ grep -o 'Xms[^ ]*' file | cut -d's' -f2 | tail -1
8192m
or more concisely:
$ sed 's/.*Xms\([^ ]*\).*/\1/' file
8192m
The positive lookbehind of PCRE (the form: (?<=RE1)RE2) can resolve the problem easily:
$ grep -oP '(?<=Xms)\S+' file.txt
3g
8192m
Explains:
-o: show only the part of a line matching PATTERN.
-P: PATTERN is a Perl regular expression.
(?<=Xms)\S+: matches all continuous non-whitespace strings which are just following the string Xms.
I will need to grep one variable for a variable pattern.
Like so
foo="--test2"
bar="--test"
echo "${foo}" | grep "'${bar}'"
Unfortunately it is not working.
Any ideas about how to achieve this?
If you use , single quotes it will take it as literal string. Remove the single quotes. Then it will throw the error for -- in your string. For that use -e option for mention that is a pattern to match.
echo "${foo}" | grep -e "${bar}"
your pattern is leading with -, -e option is needed.
this line should work for your example:
echo "${foo}" | grep -e "${bar}"
I am trying to search a text in some of the xibs in my project and replace the found text with some other text. I am using below mentioned command to perform the mentioned action but it is saying
"grep: warning: recursive search of stdin" and going to infinite waiting state.
grep -i -r --include=*.xib “$MSAwLjMxMTU4NDA0NDMgMC4wOTczNjMxNzM3NQA" myProjectPath | sort | uniq | xargs perl -e “s/$MSAwLjMxMTU4NDA0NDMgMC4wOTczNjMxNzM3NQA/$MC4xNTI5NDExODIzIDAuODA3ODQzMjA4MyAwLjE4MDM5MjE2MQA/" -pi
Please let me know where i am going wrong.
Thanx in advance.
The shell is expanding $MSAwLjMxMTU4NDA0NDMgMC4wOTczNjMxNzM3NQAas a variable and grep is producing output in the form "file: ", which sort | uniq is not correcting.
grep -l -i -r --include=*.xib '\$MSAwLjMxMTU4NDA0NDMgMC4wOTczNjMxNzM3NQA' myProjectPath | xargs perl -pi -e 's/\$MSAwLjMxMTU4NDA0NDMgMC4wOTczNjMxNzM3NQA/\$MC4xNTI5NDExODIzIDAuODA3ODQzMjA4MyAwLjE4MDM5MjE2MQA/' "$file"
We have a portion of code which states,
"diff file1 file2 | /usr/bin/grep -v "#" | /usr/bin/grep ^\> | /usr/bin/awk '{print $3}' | /usr/bin/xargs mkdir"
The whole statement is enclosed in double quotes(is a requirement of the application syntax). When the application reaches this stage , it gives the grep error.
This statement works well on the command line. But through application, gives error for grep.
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
So not sure if it is first grep or second grep which is a problem.
Seems like a problem with double quotes. Try changing your first grep to /usr/bin/grep -v '#' and the second grep to /usr/bin/grep '^>'
You are using grep -v ^> and > means "redirect".
If you for example do:
grep ^>output
all the output will be stored in the file output.
So what you need to do is to quote ^> so that it is interpreted as the pattern you are looking for:
"diff file1 file2 | /usr/bin/grep -v "#" | /usr/bin/grep "^>" | /usr/bin/awk '{print $3}' | /usr/bin/xargs mkdir"
^ ^
By the way, note all your greps can be reduced like this:
diff file1 file2 | awk '/#/ || /^>/ {print $3}' | /usr/bin/xargs mkdir
^^^ ^^ ^^^^
either contains # | |
or starts with >