views:

291

answers:

5

I want to change a number such as 1234567890 to 456-7890; is there a way to do this in Unix Shell programming?

+1  A: 
$ sed -e 's/...\(...\)\(....\)/\1-\2/'
1234567890
456-7890

You could select digit string words a bit more carefully, though not perfectly, with:

sed -e 's/\b[0-9]..\([0-9]..\)\([0-9]...\)\b/\1-\2/'
DigitalRoss
Is the '\b' operation supported where repeat counts etc are not? Wouldn't it be better simply to replace the dots with '[0-9]'? Or decide you're using GNU sed.
Jonathan Leffler
\b is a gnu extension, si. I did worry about that but reasoned that I had also provided a posix one, and that the OP would probably (1) try both, and (2) get the idea, and be able to enhance the RE on his own...
DigitalRoss
+1  A: 

G'day,

Don't forget the anchors to get the last seven digits of the string. Something like:

echo "1234567890" | sed -e 's/\([0-9]{3}\)\([0-9]{4}\)$/\1-\2/'

HTH

cheers,

Rob Wells
That doesn't work on Solaris: the {n} notation doesn't work. With GNU sed, use '-r' and drop the backslashes from the capturing parentheses.
Jonathan Leffler
sol:~>echo "1234567890" | sed -e 's/\([0-9]{3}\)\([0-9]{4}\)$/\1-\2/'1234567890this is not waht i wanted :(
@Jonathan, works on my Solaris! Dropping backslashes makes the regexp use a Perl syntax in the search pattern. I don't know what flavour of sed you're using to get that to work.
Rob Wells
@unknown, then clarify your bloody question! Or do you want us to write out the complete shell script for you?
Rob Wells
A: 

Shell scripts are basically just a bunch of commands, piped together, you can simply call any scripting language (such as Python/Ruby/Perl) as you would sed/awk/grep.

For example, using Ruby:

$ echo "Change 1234567890 to 456-7890" | ruby -e 'puts $stdin.read.gsub(/\d{3}(\d{3})(\d{3})/){|x| "#{$1}-#{$2}"}'

..which outputs:

Change 456-7890 to 456-7890

There are a few benefit of using (for example) Ruby over sed:

  • Ruby/etc will be more consistent over multiple platforms than sed/awk/grep, which tend to take different arguments and function slightly differently, depending on the which OS/distribution is being used
  • If the command becomes becomes more complicated, it is trivial to turn this into a "proper" script
dbr
-bash: ruby: command not found
Dennis Williamson
+3  A: 

@OP, you have given details about the conditions of changing the numbers. you can just use bash on your solaris 10 to do that, no need fancy regular expression in your case.

 $ n=1234567890    
 $ echo "${n:3:3}-${n:6}"
 456-7890
ghostdog74
+1  A: 

This is what DigitalRoss and Jonathan Leffler were trying to say:

echo "1234567890"|sed 's/[0-9][0-9][0-9]\([0-9][0-9][0-9]\)\([0-9][0-9][0-9][0-9]\)/\1-\2/'

This should work on all but the most brain-dead versions of sed, however it pays no attention to word boundaries, etc., or whether there are additional digits or groups of digits on the same line. It simply reformats the first ten digit sequence it finds. If you have spaces, tabs, commas or other delimiters, they can be used to further restrict the match.

Dennis Williamson