danh
danh

Reputation: 62686

replace a pattern using sed

I have a file containing a lot of text and some digits describing numbers < 1 with three digits of precision. I'd like to replace those numbers with roughly equivalent integer percentages (numbers 0-99).

0.734 -> 73
0.063 -> 6
0.979 -> 97

It would be great to round properly, but not required.

I've tried the following and several variants and I can't seem to get even one match:

sed -e 's/0\.(\d\d)/&/' myfile.txt

Which I understand to mean, match the digit 0, then the decimal, capture the next two digits and have sed replace the whole match with the captured part.

Even if I get this to work, I don't know how to handle the 0.063 -> 6 case. Sure would appreciate a helping hand on this.

Upvotes: 1

Views: 1336

Answers (3)

potong
potong

Reputation: 58568

This might work for you (GNU sed):

sed -r 's/0\.(([1-9][0-9])|0([0-9])).*/\2\3/' file

This uses alternation and backreferences (BR) to match the required pattern. If the first pattern matches the second BR will return that value and the third (BR) will be empty. Likewise if the second pattern in the alternation matches the the second BR will be empty and the third BR will return the required value.

Upvotes: 0

SwiftMango
SwiftMango

Reputation: 15304

Apart from sed answer Zoff gave, you can use awk for better implementation (with roundings):

#round down
awk '{print int($1*100)}' myfile.txt
#0.979 -> 97

#round up
awk '{printf "%.0f\n",$1*100}' myfile.txt
#0.979 -> 98

A bash only implementation:

#round down
while read n; do result=$(bc <<< "$n*100"); echo ${result%%.*}; done < myfile.txt
#round up
while read n; do result=$(bc <<< "$n*100"); printf "%.f\n" $result; done < myfile.txt

Upvotes: 0

Code Different
Code Different

Reputation: 93191

sed does support character class but use the longer POSIX name. Digits are [[:digit:]]. It's shorter to just write [0-9].

Try this:

sed -E 's/0\.([0-9][0-9]).*/\1/;s/^0//' myfile.txt

The -E flag tells it to use modern regex. There are actually 2 commands here, separated by ;:

s/0\.([0-9][0-9]).*/\1/: put the two digits following 0 and a dot into a capture group and replace the whole string with this capture group.

s/^0//: remove the leading zero from the string after the above.

Upvotes: 2

Related Questions