Hi gurus,
I have a weird requirement. I need to convert the number to english lecture.
I have 1.2 ....19 numbers
I need to convert to first second third fourth, fifth, sixth...
Is there any way convert it using unix command?
thanks in advance.
Hi gurus,
I have a weird requirement. I need to convert the number to english lecture.
I have 1.2 ....19 numbers
I need to convert to first second third fourth, fifth, sixth...
Is there any way convert it using unix command?
thanks in advance.
Some more context, please. Do you want ordinal (as posted) or cardinal numbers? What tool/system/language do you need this for? Show input an desired output.
Quick'n'dirty...
Longhand using OSX 10.7.5, default bash terminal.
#!/bin/bash
# numalpha.sh
alpha=""
n=1
numalpha()
{
if [ $n -eq 1 ]
then
alpha="first"
fi
if [ $n -eq 2 ]
then
alpha="second"
fi
if [ $n -eq 3 ]
then
alpha="third"
fi
if [ $n -eq 4 ]
then
alpha="fourth"
fi
# And so on...
}
# Test for integers numbers only.
for n in {1..4}
do
numalpha
echo "$n = $alpha"
done
Results for 4 values only.
Last login: Sat Feb 14 21:06:21 on ttys000
AMIGA:barrywalker~> cd Desktop/Code/Shell
AMIGA:barrywalker~/Desktop/Code/Shell> chmod 755 numalpha.sh
AMIGA:barrywalker~/Desktop/Code/Shell> ./numalpha.sh
1 = first
2 = second
3 = third
4 = fourth
AMIGA:barrywalker~/Desktop/Code/Shell> _
Hi,
With bash, it's more easy to use array,example ($ in begin line is my prompt):
$ nblexical=("zero" "first" "second" "third")
$ nb=2
$ echo ${nblexical[$nb]}
second
Regard.
Same machine...
#!/bin/bash
# numalpha.sh
alpha=""
numalpha()
{
if [ $1 -eq 1 ]
then
alpha="first"
fi
if [ $1 -eq 2 ]
then
alpha="second"
fi
if [ $1 -eq 3 ]
then
alpha="third"
fi
if [ $1 -eq 4 ]
then
alpha="fourth"
fi
# And so on...
}
# Test for integer numbers only.
text=( This is the 1 and only attempt to change the 4 word inside this string. )
count=0
while [ $count -lt ${#text[@]} ]
do
if [[ ${text[$count]} =~ ^-?[0-9]+$ ]]
then
numalpha "${text[$count]}"
printf "$alpha "
count=$((count+1))
fi
printf "${text[$count]} "
alpha=""
count=$((count+1))
done
Results:-
Last login: Sat Feb 14 22:54:01 on ttys000
AMIGA:barrywalker~> cd Desktop/Code/Shell
AMIGA:barrywalker~/Desktop/Code/Shell> ./numalpha.sh
This is the first and only attempt to change the fourth word inside this string.
AMIGA:barrywalker~/Desktop/Code/Shell> _
For a US English translation of the integers in the range from 0 up to and including 999999999999999999999999999999999999 into ordinal numbers, you could try something like:
#!/bin/ksh
awk '
BEGIN { # Initialize variables...
# Final single digits:
fd[0] = "zeroth"; fd[1] = "first"; fd[2] = "second"; fd[3] = "third"
fd[4] = "fourth"; fd[5] = "fifth"; fd[6] = "sixth"; fd[7] = "seventh"
fd[8] = "eighth"; fd[9] = "ninth"
# Leading single digits:
ld[1] = "one"; ld[2] = "two"; ld[3] = "three"; ld[4] = "four"
ld[5] = "five"; ld[6] = "six"; ld[7] = "seven"; ld[8] = "eight"
ld[9] = "nine"
# Final teens:
ft[10] = "tenth"; ft[11] = "eleventh"; ft[12] = "twelfth"
ft[13] = "thirteenth"; ft[14] = "fourteenth"; ft[15] = "fifteenth"
ft[16] = "sixteenth"; ft[17] = "seventeenth"; ft[18] = "eighteenth"
ft[19] = "nineteenth"
# Leading teens:
lt[10] = "ten"; lt[11] = "eleven"; lt[12] = "twelve"
lt[13] = "thirteen"; lt[14] = "fourteen"; lt[15] = "fifteen"
lt[16] = "sixteen"; lt[17] = "seventeen"; lt[18] = "eighteen"
lt[19] = "nineteen"
# Final tens:
fT[2] = "twentieth"; fT[3] = "thirtieth"; fT[4] = "fortieth"
fT[5] = "fiftieth"; fT[6] = "sixtieth"; fT[7] - "seventieth"
fT[8] = "eightieth"; fT[9] = "ninetieth"
# Leading tens:
lT[2] = "twenty"; lT[3] = "thirty"; lT[4] = "forty"; lT[5] = "fifty"
lT[6] = "sixty"; lT[7] = "seventy"; lT[8] = "eighty"; lT[9] = "ninety"
# Units:
u[2] = "thousand"; u[3] = "million"; u[4] = "billion"; u[5] = "trillion"
u[6] = "quadrillion"; u[7] = "quintillion"; u[8] = "sextillion"
u[9] = "septillion"; u[10] = "octillion"; u[11] = "nonillion"
u[12] = "decillion"; u[13] = "undecillion"
# The last entry above will only be used in overflow diagnostics. If
# more entries are added, remember that one extra entry must be added.
# The following maximum u[] subscript must be updated if more entries
# are added above.
ucnt = 13
}
# Function to print US English string corresponding to 3 digit numeric string.
function p3(units, gcnt, gnum, d1, d2, d3, d23) {
# If we have a zero and this is not the last group, nothing to print...
if(g[gnum] == 0 && gnum < gcnt) return(1)
# Grab inividual digits and last two digits...
d1 = int(g[gnum] / 100)
d23 = g[gnum] % 100
d2 = int(d23 / 10)
d3 = d23 % 10
# Hundreds to print?
if(d1)
printf("%s hundred%s", ld[d1],
d23 ? " " : (gcnt == gnum) ? "th\n" : " " units \
(t[gnum] ? " " : "th\n"))
# Print last two digits...
if(d23 || (d1 == 0 && gnum == gcnt))
if(d2 == 1)
# 10-19:
printf("%s", (gnum == gcnt) ? ft[d23] "\n" : \
lt[d23] " " units (t[gnum] ? " " : "th\n"))
else if(d2)
# 20-99:
if(d3) # [2-9][1-9]:
printf("%s-%s", lT[d2],
(gnum == gcnt) ? fd[d3] "\n" : \
ld[d3] " " units \
(t[gnum] ? " " : "th\n"))
else # [2-9]0:
printf("%s", (gnum == gcnt) ? fT[d2] "\n" : \
lT[d2] " " units \
(t[gnum] ? " " : "th\n"))
else # 0-9:
printf("%s", (gnum == gcnt) ? fd[d3] "\n" : ld[d3] " " \
units (t[gnum] ? " " : "th\n"))
return(t[gnum])
}
# Process the first field from each line in an input file...
{ # Show original input...
printf("Input:\"%s\"\n", $0)
# Check for non-digits
if(match($1, /[^[:digit:]]/)) {
print "Only digits are alloweed."
next
}
# Strip leading 0s
if(match($1, /^0+/)) {
$1 = (RLENGTH == length($1)) ? "0" : substr($1, RLENGTH + 1)
printf("Updated input:\"%s\"\n", $0)
}
# Split into groups of three digits...
ng = int((length($1) + 2) / 3)
if(ng == 0) next # skip eimpty lines
if(ng >= ucnt) { # Too big to handle?
printf("Can only handle numbers less than one %s.\n",
u[ucnt])
next
}
gw = length($1) - (ng - 1) * 3
off = 1
for(i = 1; i <= ng; i++) {
g = substr($1, off, gw)
t = substr($1, off + gw) + 0
off += gw
gw = 3
}
# Process the groups of digits...
for(i = 1; p3(u[ng + 1 - i], ng, i); i++);
}' file
This awk
script will only convert the 1st field in each line read from a file named file
. You can easily change this to read from standard input or another file and, without too much work, it could process a different set of fields from each input line.
If you want to try this on a Solaris/SunOS system, change awk
to /usr/xpg4/bin/awk
, /usr/xpg6/bin/awk
, or nawk
. This was written and tested on OS X 10.10.2.
With file
containing:
0
1
11
111
123000000456000000789
1000000000000000000000023
2034500
975310000000000000000000000987654321
1000000000000000000000000000000000000
the output produced is:
Input:"0"
Updated input:"0"
zeroth
Input:"1"
first
Input:"11"
eleventh
Input:"111"
one hundred eleventh
Input:"123000000456000000789"
one hundred twenty-three quintillion four hundred fifty-six billion seven hundred eighty-ninth
Input:"1000000000000000000000023"
one septillion twenty-third
Input:"2034500"
two million thirty-four thousand five hundredth
Input:"975310000000000000000000000987654321"
nine hundred seventy-five decillion three hundred ten nonillion nine hundred eighty-seven million six hundred fifty-four thousand three hundred twenty-first
Input:"1000000000000000000000000000000000000"
Can only handle numbers less than one undecillion.
If you need to extend the range of numbers accepted, you can find higher order names here: Wikipedia: Names of large numbers.
Hi.
For Don's data file, augmented, in file data2:"
0
1
11
111
1,011
1_012
123000000456000000789
1000000000000000000000023
2034500
975310000000000000000000000987654321
1000000000000000000000000000000000000
the perl code:
perl -M"Lingua::EN::Numbers qw(num2en num2en_ordinal)" -n -e 'chomp;
print " Cardinal for $_: ",num2en($_),"\n";
print " Ordinal for $_: ", num2en_ordinal($_),"\n";' data2
produces:
Cardinal for 0: zero
Ordinal for 0: zeroth
Cardinal for 1: one
Ordinal for 1: first
Cardinal for 11: eleven
Ordinal for 11: eleventh
Cardinal for 111: one hundred and eleven
Ordinal for 111: one hundred and eleventh
Cardinal for 1,011: one thousand and eleven
Ordinal for 1,011: one thousand and eleventh
Cardinal for 1_012:
Ordinal for 1_012:
Cardinal for 123000000456000000789: one hundred and twenty-three quintillion, four hundred and fifty-six billion, seven hundred and eighty-nine
Ordinal for 123000000456000000789: one hundred and twenty-three quintillion, four hundred and fifty-six billion, seven hundred and eighty-ninth
Cardinal for 1000000000000000000000023: one septillion and twenty-three
Ordinal for 1000000000000000000000023: one septillion and twenty-third
Cardinal for 2034500: two million, thirty-four thousand, five hundred
Ordinal for 2034500: two million, thirty-four thousand, five hundredth
Cardinal for 975310000000000000000000000987654321: nine hundred and seventy-five times ten to the thirty-third, three hundred and ten nonillion, nine hundred and eighty-seven million, six hundred and fifty-four thousand, three hundred and twenty-one
Ordinal for 975310000000000000000000000987654321: nine hundred and seventy-five times ten to the thirty-third, three hundred and ten nonillion, nine hundred and eighty-seven million, six hundred and fifty-four thousand, three hundred and twenty-first
Cardinal for 1000000000000000000000000000000000000: one times ten to the thirty-sixth
Ordinal for 1000000000000000000000000000000000000: one times ten to the thirty-sixthth
As noted in How can I convert a number to its English form in Perl? - Stack Overflow
Best wishes ... cheers, drl
While Don Cragun put in an impressive amount of work, my first thought when I saw the problem was that there is probably a Perl module for that.
Lingua::EN::Nums2Words - search.cpan.org
I don't know if it works, but you should be able to download the above Perl module using CPAN and probably find a pre-written script that will do the heavy lifting. The great part about using pre-built modules is that someone else is already maintaining the code.
Sorry DRL, I reread the post and realized that you already posted the same answer. It's worth noting that Lingua::EN::Numbers is probably not installed by default.
Hi, gandolf989.
Yes, good point. Thanks for making that comment ... cheers, drl