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.
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.
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.
The grep command is used to search text or searches the given file for lines containing a match to the given strings or words.
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
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With