Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output matching pattern whilst retaining the line they existed on - bash

Tags:

grep

sed

awk

I'm having a tedious issue that can't seem to figure out and I am sure it is pretty simple, despite searching and trying for a while.

I have a file:

$ cat test.txt
shdh blah blah balg blah 0.44d 0.55d 0.33d
shdh blah blahdf fvalg blah 6.442d 1.515d 1.23d
3858 shdh blah blah balg blah 2.46d 9.35d 0.83d
shdh blah blah balg blah 4.46d
7 hh 4.5 5.34d 5.55d
t y 6.02d
88 2.7d
0.004d
shdh blah blah balg blah 0.96d 1.113d
6 yjryjh 423.99d 0.1d blah blah 0.9d 0.117d

I'd like to match all *d values, filtering out the rest while retaining the line they reside on. ie. To return a desired output like this:

0.44d 0.55d 0.33d
6.442d 1.515d 1.23d
2.46d 9.35d 0.83d
4.46d
5.34d 5.55d
6.02d
2.7d
0.004d
0.96d 1.113d
423.99d 0.1d 0.9d 0.117d

I'm able to match the pattern, but the problem is that each value is then returned on a new line, which is not what I want:

$ cat test.txt | grep -Eo '[0-9]+\.[0-9]+d'
0.44d
0.55d
0.33d
6.442d
1.515d
1.23d
2.46d
9.35d
0.83d
4.46d
5.34d
5.55d
6.02d
2.7d
0.004d
0.96d
1.113d
423.99d
0.1d
0.9d
0.117d

Does anyone have an idea on how to accomplish and return the desired output? Possibly with tr? Although I'd assume with this method each line would then concatenate to one line, again not the desired output.

like image 563
Data Avatar asked Feb 07 '21 16:02

Data


People also ask

Which command is used to match the pattern at the end of line?

Matching the lines that end with a string : The $ regular expression pattern specifies the end of a line. This can be used in grep to match the lines which end with the given string or pattern. 11. -f file option Takes patterns from file, one per line.

Which command is used to extract lines with matching pattern from a file?

Use grep to select lines from text files that match simple patterns. Use find to find files and directories whose names match simple patterns. Use the output of one command as the command-line argument(s) to another command.

Which command is used for pattern matching in Linux?

The grep command is used to search text or searches the given file for lines containing a match to the given strings or words.


4 Answers

awk to the rescue!

$ awk '{for(i=1;i<=NF;i++) if($i~/d$/) printf "%s ",$i; print ""}' file

0.44d 0.55d 0.33d
6.442d 1.515d 1.23d
2.46d 9.35d 0.83d
4.46d
5.34d 5.55d
6.02d
2.7d
0.004d
0.96d 1.113d
423.99d 0.1d 0.9d 0.117d
like image 123
karakfa Avatar answered Nov 22 '22 22:11

karakfa


Here is a solution with sed:

sed -E 's/[^[:space:]]*[^d]([[:space:]]|$)//g'

I just inverted your initial logic: instead of displaying fields that end with d, I remove fields that don't.

like image 22
xhienne Avatar answered Nov 22 '22 22:11

xhienne


Perl oneliner:

perl -lane 'print join " ", grep {/d$/} @F' test.txt

The -e flag gives the next argument as the code to execute.
The -n flag tells perl to wrap the given code in a loop, iterating over the files of the given file(s)/stdin, without automatically printing the line.
The -a flag splits the line into fields stored in the @F array.
The -l flag handles automatically removing and re-adding the EOL newline.

like image 26
glenn jackman Avatar answered Nov 23 '22 00:11

glenn jackman


With GNU awk for FPAT:

$ awk -v FPAT='\\S*d\\>' '{for (i=1; i<=NF; i++) printf "%s%s", $i, (i<NF ? OFS : ORS)}' test.txt
0.44d 0.55d 0.33d
6.442d 1.515d 1.23d
2.46d 9.35d 0.83d
4.46d
5.34d 5.55d
6.02d
2.7d
0.004d
0.96d 1.113d
423.99d 0.1d 0.9d 0.117d

or with any awk:

$ awk '{sep=""; for (i=1; i<=NF; i++) if ($i ~ /d$/) { printf "%s%s", sep, $i; sep=OFS } print "" }' test.txt
0.44d 0.55d 0.33d
6.442d 1.515d 1.23d
2.46d 9.35d 0.83d
4.46d
5.34d 5.55d
6.02d
2.7d
0.004d
0.96d 1.113d
423.99d 0.1d 0.9d 0.117d

In comparison with other answers the above will not print a trailing blank char at the end of each output line.

like image 41
Ed Morton Avatar answered Nov 23 '22 00:11

Ed Morton