grep words from sentences having a dot - grep

I am unable to grep words after the dot.
Example,
I want to grep some words from sentences like :
PF03059.12
PF03330.13
PF13041.15
PF13812.65
PF01535.77
I tried
grep -oh "\w*PF\.*\w*"
grep -oh "\w*PF\.[0-9][0-9]\w*
and the results are
PF03059
PF03330
PF13041
PF13812
PF01535
I would like to fetch the ones after the decimal as well.
Thanks

is this what you want?
grep -e "\w*PF[0-9]*\.\w*" -h

For a file like this:
$ cat file1
This is sentence PF03059.12 and should be ok
This is sentence PF03330.13 and should be ok
This is sentence PF13041.15 and should be ok
This is sentence PF13812.65 and should be ok
This is sentence PF01535.77 and should be ok
This seems to be enough:
$ grep -o "PF.[^ ]*" file1
PF03059.12
PF03330.13
PF13041.15
PF13812.65
PF01535.77
It actually captures all chars after PF (.*)and stops in first found space [^ ]

How about to use awk instead grep? This will allow to write simple and more clear solution without regular expressions. Just try this:
awk -F. '{print $2}'
Explanation: -F. set field delimiter to dot . then print $2 just print second field

Input file:
$cat file.txt
PF03059.12
PF03330.13
PF13041.15
PF13812.65
PF01535.77
PF13812
PF01535
XXXXX
PFABC.666
123.456
grep command: (using -P PCRE)
grep -P 'PF\d+(?:\.\d+)?' file.txt
PF03059.12
PF03330.13
PF13041.15
PF13812.65
PF01535.77
PF13812
PF01535
If you don't want to match line without decimals like PF13812, change regex to:
grep -P 'PF\d+:\.\d+' file.txt

Related

How to display two substring from a line?

How can we find two substrings within a line in particular order using grep?
For example:
grep -c "word1" | grep -r "word2" logs
gives if string has both word1 and word2. I am looking for string which has "... word1.... word2..."
Try a regex in grep like grep -E "word1.*word2"
$ echo -e 'both word1 and word2. \nI hich\n has "... word1.... word2..."' | grep -E "word1.*word2"
both word1 and word2.
has "... word1.... word2..."
You may need a better regex to match exactly the words, but that is not your question.

How to grep repeated strings on a single line?

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.

print filename if several matches are present in file

I want to print the filename if only ALL the matches are present... on different lines
grep -l -w '10B\|01A\|gencode' */$a*filename.vcf
this prints out the filename, but not only if ALL three matches are present.
Would you consider to try awk? awk may solve it in following method,
awk '/10B/&&/01A/&&/gencode/{print FILENAME}' */$a*filename.vcf
try following, just edited your solution a bit.
grep -l '10B.*01A.*gencode' Input_file
With grep and its -P (Perl-Compatibility) option and positive lookahead regex (?=(regex)), to match patterns if in any order.
grep -lwP '(?=.*?10B)(?=.*?01A)(?=.*?gencode)' /path/to/infile
grep -l 'pattern1' files ... | xargs grep -l 'pattern2' | xargs grep -l 'pattern3'
From the grep manual:
-l, --files-with-matches
Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match. (-l is specified by POSIX.)

Grep digits after match

I would like to grep digits inside a set of parentheses after a match.
Given foo.txt below,
foo: "32.1" bar: "42.0" misc: "52.3"
I want to extract the number after bar, 42.0.
The following line will match, but I'd like to extract the digit. I guess I could pipe the output back into grep looking for \d+.\d+, but is there a better way?
grep -o -P 'bar: "\d+.\d+"' foo.txt
One way is to use look ahead and look-behind assertions:
grep -o -P '(?<=bar: ")\d+.\d+(?=")'
Another is to use sed:
sed -e 's/.*bar: "\([[:digit:]]\+.[[:digit:]]\+\)".*/\1/'
You could use the below grep also,
$ echo 'foo: "32.1" bar: "42.0" misc: "52.3"' | grep -oP 'bar:\s+"\K[^"]*(?=")'
42.0

grep is not working inside while loop

I have two files
File1
area a
area b
areaf
File2
area a :aaaa
area b:bbbb
area3:abc
areaf:hsg
area4:uhg
area5:yutr
while read -r line
do
grep -w ^line File2 | cut -d ":" -f2
done < File1
Desired output
aaaa
bbbb
hsg
actual output
grep: can't open a
area a
grep: cant open b
area3:abc
areaf:hsg
area4:uhg
area5:yutr
but when i run grep -w ^"area a" File2 | cut -d ":" -f2 it is giving the correct output :
aaaa
Please assist me on this. i tried for loop also. no success. grep is not working inside loop.
Your variable line might contain "special characters". For example, a space that might be interpreted as a separator by the shell. Or some characters that might be interpreted as pattern metacharacter by grep.
You both need to use fgrep and to quote your variable (I'm not sure -w add anything to that command -- why do you feel the need of it?):
fgrep -w "$line"
But doing so you loose the ability to locate "the first character"
An other option if the "start of line" match is required is to escape the search string:
while read -r line
do
line=$(echo "$line" | sed -e 's/[]\/$*.^|[]/\\&/g')
grep -w "^$line" File2 | cut -d ":" -f2
done < File1
You can achieve the same result without a loop, since grep can read patterns from a file via the -f option. This will be more robust:
grep -f input1 input2 | cut -d: -f2
Gives:
aaaa
bbbb
hsg

Resources