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
    What have you tried ? It could be done in any scripting language of your choice and familiarity – amisax Dec 22 '16 at 5:57
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
  • 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 '16 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 ; – Stéphane Chazelas Dec 22 '16 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.