电子邮件地址的整数形式

今天在浏览别人博客时,偶然看到博主的电子邮件地址很奇怪,是dc -e xxxxxxxxxxxxxP的形式,在shell下运行了,果然输出了电子邮件地址,好神奇啊。

这么神的电子邮件地址,我也想有一个,所以就查了下,原来dc是linx下的栈式任意精度计算器,用逆波兰形式来表示,所有的操作都在栈中进行。还有个bc命令,它与dc是什么关系呢,在UNIX下,bc是dc的一个前端,就是说bc实际上是用dc而完成计算的,它只不过作了一些预处理工作,使它更方便用户使用;而在Linux下,bc用的是GNU bc,它是一个与dc毫不相关的独立程序。

说了这么多,那我怎么才能得到这么神奇的电子邮件地址呢?
首先要明白那个dc命令是什么意思,这个可以man dc查看。dc -e xxxxxxxxxxxxxP,是将xxxxxxxxxxxxx压栈,然后P命令将栈顶以字符串的形式输出,字符串中每个字符的值都是通过取模(模为256)得到的,结果就是电子邮件地址了。

这样,我们要做的就是把电子邮件地址这个字符串转为一个整数,整数的值为字符串按权值从左到右减的形式算得的值,基数为256,也即8位bit的ASCCI码的模。
计算公式x(i) * 256^(i-1) + x(i-1) * 256^(i-1-1)+……+x(1):

下面给出字符串到大整数转换的bash脚本string-to-big-number.sh

[bash]
#! /bin/sh

#函数作用
#把一个任意长度的字符串转化为一个大整数,字符串从左到右权值变小

#可以给一个邮件地址作为参数,然后得到一个大整数
#然后可以用dc命令从整数得到电子邮件地址
#dc -e xxxxxP
#xxxxx为运行程序结束时得到的一个长整数
#P为dc中的输出命令

script_name=$(basename $0) #script name

#一个简单的帮助函数
usage ()
{
echo
echo "USAGE: $script_name your_email_address"
echo
echo
echo "Example:"
echo " $script_name example@example.com"
echo
echo
exit 1
}

if [[ -z "$@" ]]
then
usage
else

email_address="$@"
fi

declare -a num_array
#od命令是为了将字符串转为整数形式
#tr命令是为了去除od命令产生的每16字节的回车。不过试了下,好像可以不用去除
#直接就可以num_array=(`echo $email_address | od -An -t dC `)

num_array=(`echo $email_address | od -An -t dC | tr -d "\n"`)
num_array=(`echo $email_address | od -An -t dC `)

answer=$(echo ${num_array[0]}*${num_array[2]} | bc)

length=${#num_array[@]}

tmp=1
answer=0

for(( i=$length-1;i>=0;i– ))
do
tmp=${num_array[$i]}
for(( j=$length-1-$i;j>0;j– ))
do
tmp=$(echo $tmp*256|bc)
#这里用到tr命令是因为,当tr的输出长度超过68位时会输出一个断行的标志
#字符串"\ ",这里把它去除,不然当你的输出字符串超过27时就会出错
#也可以这样tmp=$(echo $tmp|tr -d ‘\\\ ‘)
tmp=$(echo $tmp|tr -d "\\\\\ ")
done
answer=$(echo $answer+$tmp | bc)
#这里用到tr命令是因为,当tr的输出长度超过68位时会输出一个断行的标志
#字符串"\ ",这里把它去除,不然当你的输出字符串超过27时就会出错
#也可以这样tmp=$(echo $tmp|tr -d ‘\\\ ‘)
answer=$(echo $answer|tr -d "\\\\\ ")

done

echo $answer
[/bash]

试用举例:
用我自己的邮箱测试下:

[code]
>./string-to-big-number.sh lonelyibex@gmail.com
158478336724523558231355197806041675486339888278794
[/code]

如何找回邮件地址呢?

[code]
>dc -e 158478336724523558231355197806041675486339888278794P
lonelyibex@gmail.com
[/code]

哈哈,出来了吧。
这样就再也不怕网络垃圾邮件了。

再看一个好玩的:

[code]
>dc -e 6210311416885776882064095332186488690375381188833444908746308655633507
3029213711782268384217314297776641370186061300200882451991072479873368332294
0386450189284826824257730936022632689790257544368080047034455808265517031663
1506345335835739126208462505365174992730467747066981287672993055897050191074
4147189069583852539002525228214538P
I'm lonelyibex,welcome to send me messages. My email:lonelyibex@gmail.com My jabber ID:fungo@jabber.org irc:lonelyibex (irc.freenode.net)
[/code]

3 thoughts on “电子邮件地址的整数形式

  1. 叶三

    在下也是首先看了骨头页面的东西,然后翻manpage结果没看明白。博主这个脚本倒是很明白的,不过有点瑕疵,就是效率问题,你这个复杂度貌似是n^2,我觉得后面这么改一下就可以减少时间复杂度,
    tmp=1
    answer=0
    pow=0
    for(( i=$length-1;i>=0;i-- ))
    do
    tmp=${num_array[$i]}
    pow=$(echo $length-1-$i|bc)
    pow=$(echo $pow|tr -d '\\ ')
    tmp=$(echo $tmp*256^$pow|bc)
    tmp=$(echo $tmp|tr -d '\\ ')
    answer=$(echo $answer+$tmp | bc)
    answer=$(echo $answer|tr -d '\\ ')
    done

    echo $answer

    最后博主给出的那段文字,在我的破机器上竟然用了
    real 0m41.570s
    user 0m11.950s
    sys 0m30.826s
    改过之后单循环效果不错
    real 0m1.692s
    user 0m0.448s
    sys 0m1.254s

    Reply
  2. kongove

    谢谢分享,很久很久以前见一个学长用这个展示邮箱地址,好奇很久了,终于知道了。

    # dc -e 7622548245278139593241827972721158335520736188749447393301189370122P

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>