10

I have a file with content like

12345

I need to convert this kind of strings like this:

"0"->"a"
"1"->"b"
...
"9"->"j"

So, 12345 should result in abcde. I want to achieve this via the shell (bash). What is the best way to do this?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
vinnitu
  • 4,234
  • 10
  • 41
  • 59

7 Answers7

17

In any shell, you could use:

echo "$string" | tr 0123456789 abcdefghij

Or, in Bash and without a pipe:

tr 0123456789 abcdefghij <<< "$string"

(where the double quotes might not be necessary, but I'd use them to be sure).

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • fixed a bug in your 2nd example – glenn jackman Feb 17 '11 at 17:57
  • This does not work for all letters of the alphabet – Roel Van de Paar Oct 10 '22 at 23:39
  • @RoelVandePaar — it doesn't try to work for all letters; that isn't the task. It converts digits 0 to 9 to letters a to j. How do you think it should work “for all letters of the alphabet”? – Jonathan Leffler Oct 10 '22 at 23:59
  • There are several alternative ways of specifying the digits and letters. Both `'0-9'` and `'[:digit:]'` map to 0123456789, and `'a-j'` maps to `'abcdefghij'`. The single quotes are a good idea around the (verbose) `'[:digit:]'` term; the others do not need the single quotes, but they do no harm either. I don't recommend the character class, but `tr 0-9 a-j` is succinct. – Jonathan Leffler Nov 14 '22 at 16:11
8
 echo 12345 | tr '[0-9]' '[a-j]'
akira
  • 6,050
  • 29
  • 37
  • 1
    Say if I have to do the aliter. Map words to numbers. Which is, a->1, b->2 ... and so on. Why doesnt ``echo hello | tr '[a-z]' '[1-26]' `` work? – FlyingAura Sep 25 '16 at 17:18
  • 1
    @user3426358 Because sed only translates single characters. Even the translation `tr 'z' '26'` alone is not possible. See also [Is there a tr for translating into longer strings](http://unix.stackexchange.com/questions/16281/is-there-a-tr-for-translating-into-longer-strings). – Socowi Nov 05 '16 at 12:05
2

With sed's map operator.

sed 'y/12345/hWa!-/' <<< '2313134'
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
1
tr 0123456789 abcdefghij < filename
frankc
  • 11,290
  • 4
  • 32
  • 49
1

There's more than one way to do it:

perl -lnaF -e 'print map chr($_+97), @F' file
abcdefghij
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 1
    That's pretty obscure and indirect, even for Perl. It might be appropriate to use the `tr///` operator...but then, it is Perl and TMTOWTDI. – Jonathan Leffler Feb 17 '11 at 18:32
0

Here is a solution which works for all letters of the alphabet (with thanks):

inputnr=1  # a
declare -i i=$[ 97-1+${inputnr} ]
c=$(printf \\$(printf '%03o' $i))
echo "char:" $c
inputnr=26  # z
declare -i i=$[ 97-1+${inputnr} ]
c=$(printf \\$(printf '%03o' $i))
echo "char:" $c
Roel Van de Paar
  • 2,111
  • 1
  • 24
  • 38
  • To make the output uppercase `A-Z` for `1` to `26` as input, do: `c=$(printf \\$(printf '%03o' $i) | tr '[:lower:]' '[:upper:]')` – Roel Van de Paar Oct 10 '22 at 23:43
  • Under your scheme, what would 12345 be converted to? The question indicates that it should be either 'abcde' or 'bcdef'. It certainly seems to want to transform each digit separately. People quite often use 'number' instead of 'digit', especially if English is not their first language. – Jonathan Leffler Oct 11 '22 at 12:54
  • The question does not specifically state that all numbers need to be converted at once. – Roel Van de Paar Oct 12 '22 at 22:05
0

Easy method in bash if you're okay with using arrays.

alphabet=({A..Z})
number=8
letter="${alphabet[$number]}"

With this method, A will be 0, B will be 1, etc.

If you instead want A to be mapped to 1, just change the array value to this.

alphabet=('' {A..Z})
Eduardo Perez
  • 503
  • 7
  • 22