1

I am trying to do a assignment for university, but I am currently stuck. The goal is to read some phone numbers and reverse the order of the first 3 digits and put them in brackets. I can get it to read the phone numbers but not do the reversal of the digits.

ex: input

214 4234-5555

ex: output

412 4234-5555

this is what I have so far

sed -r "s/([0-9]), ([0-9]), ([0-9])/\3\2\1/g" phone.txt
5

To modify OP's attempt

$ cat ip.txt
214 4234-5555
foo 123 4533-3242

$ sed -r 's/([0-9])([0-9])([0-9])/\3\2\1/' ip.txt
412 4234-5555
foo 321 4533-3242

$ # adding parenthesis as well
$ sed -r 's/([0-9])([0-9])([0-9])/(\3\2\1)/' ip.txt
(412) 4234-5555
foo (321) 4533-3242

$ # if ERE is not supported
$ sed 's/\([0-9]\)\([0-9]\)\([0-9]\)/(\3\2\1)/' ip.txt
(412) 4234-5555
foo (321) 4533-3242
  • Note that some sed implementation would need -E instead of -r
  • Use single quotes unless you need interpolation, see also https://mywiki.wooledge.org/Quotes
  • ([0-9]), ([0-9]), ([0-9]) means matching 3 digits separated by comma and space
  • g modifier is needed if all matches in a line should be changed


For a generic solution, i.e defining number of digits to reverse as a numeric argument

$ perl -pe 's/\d{3}/reverse $&/e' ip.txt
412 4234-5555
foo 321 4533-3242
$ perl -pe 's/\d{3}/sprintf "(%s)", scalar reverse $&/e' ip.txt
(412) 4234-5555
foo (321) 4533-3242
  • 1
    +1'ed, good answer, especially perl . You may want to include POSIX grouping \([0-9]\) since POSIX sed doesn't have -r , neither does FreeBSD sed. – Sergiy Kolodyazhnyy Feb 19 '18 at 5:55
  • 1
    @SergiyKolodyazhnyy, FreeBSD's sed now does support -r for compatibility with GNU sed. GNU sed now also supports -E for compatibility with BSDs and also because it will be the one specified in the next major version of the POSIX specification. – Stéphane Chazelas Feb 19 '18 at 16:19
1

Here's a very long, convoluted, and probably unnecessary sed, but here it is nonetheless because fun:

sed -re 'h;    s/^([0-9]*) *(.*)/\1\n/;  :1 s/(.)(.*\n)/\2\1/;t1;  s/.//;  s/^(.*)$/\(\1\)/; x;s/([0-9]{3})(.*)/\2/;x;G;s/\n//'

This works as so:

      # pretend 214 4234-5555 is the current line
h;    # copy the current line into hold space
s/^([0-9]*) *(.*)/\1\n/;  # keep only first 3 numbers, 214
:1 s/(.)(.*\n)/\2\1/;t1;  s/.//;  # reversing string in sed, 
                                  # see notes below; 214 becomes 412
s/^(.*)$/\(\1\)/;  # After string is reversed, add brackets; (412)
x;s/([0-9]{3})(.*)/\2/; # swap hold and pattern buffer, 
                        # delete first 3 chars; 
                        # pattern space now is <space>4234-5555

x;G;s/\n// # swap again, append hold buffer to pattern buffer; 
            # now pattern buffer is (412)<newline> 4234-5555; 
            # finally delete newline; we get (412) 4234-5555

And that's how it looks like in action:

$ printf "214 4234-5555\n123 3333\n" | sed -re 'h;    s/^([0-9]*) *(.*)/\1\n/;  :1 s/(.)(.*\n)/\2\1/;t1;  s/.//;  s/^(.*)$/\(\1\)/; x;s/([0-9]{3})(.*)/\2/;x;G;s/\n//'
(412) 4234-5555
(321) 3333

Note: String reversal originally found on Stephane Chazelas's comment

0

Method1

I have used below method get the same result

i=`awk '{print $1}' example.txt| rev`
awk -v i="$i" '{print i,$2}' example.txt

Output

412 4234-5555

Method2

sed  's/\(.\)\(.\)\(.\)/\3\2\1/' example.txt

output

412 4234-5555
  • I think your first line is missing some command substitution. – Jeff Schaller Feb 20 '18 at 3:21
  • @JeffSchaller Added the ` in first line which was missing. As checked it working fine now. Kindly let me know for any confusion – Praveen Kumar BS Feb 20 '18 at 15:16
  • Still no parenthesis; and what about when there’s more than one line of input? Any comment to the OP to teach them what was wrong with their attempt? Otherwise they’re stuck copy-pasting solutions that they don’t understand. – Jeff Schaller Feb 20 '18 at 16:02
-3

If you have the number in phone.txt as "xxx xxx-xxxx", then you can use the below:

!/bin/bash

echo '('$(cat phone.txt | cut -d ' ' -f1 | rev)')'

  • 1
    That only prints the 1st three numbers reversed, it removes the rest. And this will print one parenthesis at the top of the file, one at the bottom and everything else in the middle. You also don't need the cat, just cut -d ' ' -f1 phone.txt | rev would do the same (not very helpful) thing. – terdon Feb 19 '18 at 10:32

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.