2

I have an output like this:

(2+05:10)
(10:19)
(00:45)

This output represents day hours and minute. I would like to replace the ':' with 'd','h' and 'm' respectively, to get this

2d05h10m
10h19m
00h45m

Presently, I tried,

 sed -e 's/(//g; s/)//g; s/+/:/g'|awk '{split($0,s,":"); print s[1]"d" s[2]"h"s[3]"m"}')

which gives (and here I mess up !)

6d05h20m
3d15h17m
1d02h27m
00d08hm
00d11hm
02d25hm
02d30hm
16d50hm
5d00h39m
21d48hm
1
  • 1
    What have you tried ? It could be done in any scripting language of your choice and familiarity
    – amisax
    Dec 22, 2016 at 5:57

3 Answers 3

5

Sounds like

< file tr '+:)' dhm | tr -d '('

Would do it. Or to match on that pattern more explicitly:

sed 's/(\([0-9]\{1,\}\)+\([0-9]\{1,\}\):\([0-9]\{1,\}\))/\1d\2h\3m/g
     s/(\([0-9]\{1,\}\):\([0-9]\{1,\}\))/\1h\2m/g' < file

Which with some sed implementations you can simplify using extended regular expressions to:

sed -E 's/\(([0-9]+)\+([0-9]+):([0-9]+)\)/\1d\2h\3m/g
        s/\(([0-9]+):([0-9]+)\)/\1h\2m/g' < file

Or with a single s command with perl:

perl -pe 's{\((?:(\d+)\+)?(\d+):(\d+)\)}{
    ($1 && "$1d") . "$2h$3m"}ge' < file

Or:

perl -pe 's/\((\d*\+?\d+:\d+\))/$1 =~ y|+:)|dhm|r/ge' < file
2
  • sed 's/(\([0-9]\{1,\}\)+\([0-9]\{1,\}\):\([0-9]\{1,\}\))/\1d\2h\3m/g s/(\([0-9]\{1,\}\):\([0-9]\{1,\}\))/\1h\2m/g' < file does not introduce d m h in the string. Could you help.
    – ankit7540
    Dec 22, 2016 at 8:43
  • 1
    @ankit7540, note that it has to be on 2 lines as shown. If you want to put it on one line, you need to separate the 2 s commands with a ; Dec 22, 2016 at 9:14
1

A simple (but slightly inefficient) perl script should suffice

cat output_file | perl simple.pl 

simple.pl

@seps=split /:/,"d:h:m"; 
while(<>) {
 chomp ;
 $_=~s/[\(\)]//g;  #remove braces
 @x = split /:/, $_;   #get parts
 $s="";
 for($i=$#x,$j=$#sep;$i>=0; $i--,$j--) { #iterate on parts and corresponding separator 
    $s=$x[$i].$seps[$j].$s;              #create print string 
 }
 print "$s\n";                           #print this line
}
1

You're missing an awk solution. Here is one that omits zero elements:

parse.awk

# Start with empty variables
{ d = h = m="" }

# Determine format and set variables accordingly.
# Force numeric interpretation by multiplying by one
NF==5 { d = $2*1; h = $3*1; m = $4*1 }
NF==4 { d = ""  ; h = $2*1; m = $3*1 }

# Only set value if the number is greater than zero
{
  d = d > 0 ? d "d" : ""
  h = h > 0 ? h "h" : ""
  m = m > 0 ? m "m" : ""
}

length(d h m)  > 1 { print d h m }
length(d h m) == 0 { print "Now" }

Run it like this:

awk -f parse.awk -v FS='[()+:]' file

Output:

2d5h10m
10h19m
45m

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .