Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm currently trying to modify an echoed string of alphanumeric characters by piping it to sed. The area I'm interested in modifying is a block of numbers, which I would like to make 8 characters long by inserting an appropriate number of zeros to the front of it. For example:

Input:

loremipsumdolorsit2367amet

Desired output:

loremipsumdolorsit00002367amet

Is it possible to do this with sed? The blocks of numbers I'm dealing with are less than 8 characters, if that helps. I'm not sure if this post helps. Thanks in advance!

Edit: there is only one block of numbers in each string.

share|improve this question
add comment

5 Answers

up vote 6 down vote accepted

This assumes that there is some non-numeric text after the number:

echo "loremipsumdolorsit2367amet" \
| sed -r -e 's/[0-9]/0000000&/' -e 's/0*([0-9]{8}[^0-9])/\1/'

Result: loremipsumdolorsit00002367amet

This doesn't assume that:

... | sed -r -e 's/[0-9]/0000000&/' -e 's/0*([0-9]{8}([^0-9]|$))/\1/'

These use the ERE patterns for sed. Many sed implementations use the -r flag to specify this; some use the -E flag; some use both. Currently the ability to use ERE patterns in sed is not part of the POSIX standard, but there's been talk of adding it to the standard. I haven't encountered a modern sed implementation which doesn't have the ability to use ERE patterns in one way or another.

In some cases there are things you can do using ERE patterns that you can't do using the default sed patterns (BREs). See the comments to this answer. But in the present case, the use of ERE patterns is just for convenience. As sch says in a comment, you can omit the -r (or -E) flag, and just replace the (...) with \(...\) and the {8} with \{8\}. My original answer made use of +, which is also not part of BRE patterns; but in fact this wasn't necessary to the solution.

share|improve this answer
    
Hmm, when I try this, I get the error sed: illegal option --- r –  sourisse Oct 16 '12 at 3:25
    
Different seds use different flags for extended patterns. Some use -r, others use -E. Some accept both. –  dubiousjim Oct 16 '12 at 3:26
    
Ah, great. Switching it to -E worked for me. What kinds of things determine which type of sed one has? –  sourisse Oct 16 '12 at 3:31
    
Gnu sed accepts -r, so too BusyBox sed, FreeBSD accepts both, looks like Mac OS X accepts only -E. –  dubiousjim Oct 16 '12 at 3:34
2  
Neither -r nor -E are standard. The standard sed only accepts BRE (basic regular expressions). Just replace + with \{1,\} and (...) with \(...\) and {...} with \{...\} and it will be standard and you won't have to worry. (<<< is not standard either) –  Stephane Chazelas Oct 16 '12 at 7:08
show 2 more comments

That's possible with perl:

perl -e 'my $a="loremipsumdolorsit2367amet"; $a =~ s/([0-9]+)/sprintf("%010d",$1)/e; print $a'

Got:

loremipsumdolorsit0000002367amet

To process all input lines:

perl -pe 's/([0-9]+)/sprintf("%010d",$1)/e'
share|improve this answer
    
This is interesting, thank you. Is it possible for this command to accept the output of a pipe instead of requiring the string to be entered as a variable? I have a lot of such strings, so entering them all is too time-consuming... –  sourisse Oct 16 '12 at 3:27
    
@sourisse Gilles has updated my answer –  warl0ck Oct 16 '12 at 14:27
    
The only thing I got working (with a function cal in the replacement). Thanks! –  Raphael Jun 3 '13 at 20:09
add comment

Also not sed, but here's a -slightly convoluted- (GNU) awk alternative:

echo loremipsumdolorsit2367amet | awk '{gsub( /[0-9]+/, sprintf( "%08d", gensub(/[^0-9]/, "","g"))); print}' 
loremipsumdolorsit00002367amet
share|improve this answer
add comment

With any sed:

sed 's/[0-9]\{1,\}/0000000&/g;s/0*\([0-9]\{8,\}\)/\1/g'
share|improve this answer
    
Your 0*\([0-9]\{8,\}\) is another good solution to not requiring non-numeric text after the numbers. It's more elegant than what I proposed in my edited answer, though my proposal also works---so long as the original numbers never exceed 8 digits, which the question does stipulate. But I do like the strategy you used. –  dubiousjim Oct 16 '12 at 15:14
add comment

Using loops in sed:

echo loremipsumdolorsit2367amet | sed -r -e  :a -e 's/([^0-9])([0-9]{1,7}[^0-9])/\10\2/;ta'

Guru.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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