Reputation: 215
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.
Upvotes: 6
Views: 118
Reputation: 246764
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.
Upvotes: 3
Reputation: 203229
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.
Upvotes: 2
Reputation: 6134
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.
Upvotes: 3
Reputation: 67467
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
Upvotes: 3