标题: [已结][超级感谢netbenton和其他老师的帮助]IP类型转换
[打印本页]
作者: cz1314
时间: 2009-1-3 06:23
标题: [已结][超级感谢netbenton和其他老师的帮助]IP类型转换
现在ip的表示方式有2种:
一种是数字型 例如:3758096383
另一种是大家常用的点分十进制 例如:223.255.255.255
我来解释下这2中ip 格式是如何进行转换的。
这个过程可以用windows的计算器实现,
首先打开科学计算方式,在十进制下输入数字型ip,转换成16进制
比如 3758096383 转换为16进制就是 DFFFFFFF
那么这个IP实际上就是dF.FF.FF.FF
分别把DF和FF转化为十进制,那么就是 223和255
最后的转换结果就是:233.255.255.255。原理比较简单。
我这里有一个文本ip.txt,内容如下:
=====txt=====
50331648 50331903 US
50331904 50332671 US
50332672 50332927 US
50332928 50333695 US
50333696 50333951 US
... ...
... ...
50333952 50334719 US
============
文本中的数字就是 ip地址。
我想写个批处理能把这个文本中的数字型ip 转换成点分十进制格式,并输出到另外一个文本保存。
当中涉及到10进制和16进制的多次转换和输出。由于本人批处理水平太菜,整了3天也没整出来,
特在此请象各位大侠请教,感谢万分! ! !
感谢各位老师的帮助。 请打下看看下面这段代码如何? 因为ip.txt数据量巨大,有700万条。
=====
echo off&setlocal enabledelayedexpansion
set hex=0123456789ABCDEF
for /f "usebackq tokens=1,2*" %%i in ("ip.txt") do (
if not "%%i"=="" set var=&set h=&set s=%%i&call:lp
set/a ha=0x!var:~-8,2!,hb=0x!var:~-6,2!,hc=0x!var:~-4,2!,hd=0x!var:~-2,2!
set str1=!ha!.!hb!.!hc!.!hd!
if not "%%j"=="" set var=&set h=&set s=%%j&call:lp
set/a ha=0x!var:~-8,2!,hb=0x!var:~-6,2!,hc=0x!var:~-4,2!,hd=0x!var:~-2,2!
set str2=!ha!.!hb!.!hc!.!hd!
>>ip1.txt echo !str1! !str2! %%k
)
start "" "ip1.txt"
pause&goto :eof
:lp
set/a m=s/16,n=s%%16
set n=!hex:~%n%,1!
set h=%n%%h%
if %m% geq 16 set s=%m%&goto lp
set m=!hex:~%m%,1!
set var=0%m%%h%
=========
[ Last edited by HAT on 2009-1-16 at 15:44 ]
作者: 3742668 时间: 2009-1-3 11:06
用for+ping很简单.
作者: pooronce
时间: 2009-1-3 11:55
@echo off
del IP_out.txt
for /f "tokens=1,2,3" %%i in (ip.txt) do @call :output %%i %%j %%k
type IP_out.txt
pause&goto :eof
:output
set ip1=
set ip2=
call :ipconv "ip1" %1
call :ipconv "ip2" %2
echo %ip1% %ip2% %3>>IP_out.txt
goto :eof
:ipconv
rem 注意,此过程只能IP首位在127以下,即2147483647最大
set varname=
set tmpIP=
set _IP_a=
set _IP_b=
set _IP_d=
if %~2 gtr 2147483646 (echo 数字太大,转呼过程2&call :ipconv2 %1 %2&goto :eof)
set "varname=%~1"
set tmpIP=%2
set /a _IP_a=tmpIP^>^>24
set /a _IP_b=(tmpIP^>^>16)^&255
set /a _IP_c=(tmpIP^>^>8)^&255
set /a _ip_d=tmpIP^&255
set %varname%=%_IP_a%.%_IP_b%.%_IP_c%.%_IP_d%
goto :eof
:ipconv2
set tmpIP=
set varname=
rem Hmmm...用ping的方式应该无限制吧 囧
set "varname=%~1"
set tmpIP=%2
::这行的比较搞不定,不搞了,哪位有兴趣试试吧,过了31位的数就不能直接比较了,要字符串比较很麻烦呀很麻烦
::if %tmpIP% gtr 4294967294 (echo 大哥!超范围了,你自己处理吧,我做不来了 囧rz&set %varname%=数字太大,自行处理!&goto :eof)
for /f "tokens=2" %%i in ('ping %tmpIP% -n 1 -w 0') do set %varname%=%%i&goto :eof
作者: slore
时间: 2009-1-3 12:20
直接ping会转换的……
作者: pooronce
时间: 2009-1-3 12:25
Quote: |
Originally posted by slore at 2009-1-3 12:20 PM:
直接ping会转换的…… |
|
ping效率比较低...
能想办法解决31位限制就ok了...
作者: slore
时间: 2009-1-3 12:35
-n 1 -w 1 速度不算慢
作者: pooronce
时间: 2009-1-3 13:11
慢的
在大量转换的场合,时间消耗不可胜数的
你看上面,我用0的,随便遇到几个高值ip,就会小卡一会儿了
作者: netbenton
时间: 2009-1-3 15:32
标题: 回复3楼
@echo off
del IP_out.txt>nul
for /f "tokens=1,2,3" %%i in (ip.txt) do @call :output %%i %%j %%k
type IP_out.txt
pause&goto :eof
:output
set ip1=
set ip2=
call :ipconv "ip1" %1
call :ipconv "ip2" %2
echo %ip1% %ip2% %3>>IP_out.txt
goto :eof
:ipconv
rem 注意,此过程只能IP首位在127以下,即2147483647最大
if %~2 gtr 2147483646 (echo 数字太大,转呼过程2&call :ipconv2 %1 %2&goto :eof)
set ou=
:ipconv1
set varname=
set tmpIP=
set _IP_a=
set _IP_b=
set _IP_c=
set _IP_d=
set "varname=%~1"
set tmpIP=%2
set /a _IP_a=tmpIP^>^>24
if defined ou set /a _IP_a=_IP_a+128
set /a _IP_b=(tmpIP^>^>16)^&255
set /a _IP_c=(tmpIP^>^>8)^&255
set /a _ip_d=tmpIP^&255
set %varname%=%_IP_a%.%_IP_b%.%_IP_c%.%_IP_d%
goto :eof
:ipconv2
rem 增加此过程处理IP首位在127以上的代码
set "var=%~2"
set varf=%var:~0,1%
set varb=1%var:~1%
set /a varf=%varf%-2
set /a varb=%varb%-147483648
if %varb% lss 1000000000 set /a varf=varf-1
set /a var=%varf%*1000000000+%varb:~-9%
set ou=128
call :ipconv1 %~1 %var%
goto :eof
作者: pooronce
时间: 2009-1-3 17:06
思路不错
不过有些东西你没处理好
试下这个ip.txt:
50331648 1033418400 US
4000000001 50332671 US
3549476416 50332927 US
4000000000 50333695 US
4007483643 50333951 US
2123369536 50334719 US
作者: pooronce
时间: 2009-1-3 17:09
改进版来喽:
@echo off
del IP_out.txt>nul
for /f "tokens=1,2,3" %%i in (ip.txt) do @call :output %%i %%j %%k
type IP_out.txt
pause&goto :eof
:output
set ip1=
set ip2=
call :ipconv "ip1" %1
call :ipconv "ip2" %2
echo %ip1% %ip2% %3>>IP_out.txt
goto :eof
:ipconv
rem 注意,此过程只能IP首位在127以下,即2147483647最大
set _hmark=
set varname=
set tmpIP=
set _IP_a=
set _IP_b=
set _IP_c=
set _IP_d=
set "varname=%~1"
set tmpIP=%2
if %~2 gtr 2147483646 call :iptrip %2 "tmpIP" "_hmark"
if "%_hmark%"=="Error" set "%varname%=此IP错误"&goto :eof
set /a _IP_a=tmpIP^>^>24
if "%_hmark%"=="1" set /a _IP_a+=128
set /a _IP_b=(tmpIP^>^>16)^&255
set /a _IP_c=(tmpIP^>^>8)^&255
set /a _ip_d=tmpIP^&255
set %varname%=%_IP_a%.%_IP_b%.%_IP_c%.%_IP_d%
goto :eof
:iptrip
rem 此过程处理IP首段过127的部分,参数2为要处理的变量名,参数3为标记名
if "%1"=="2147483647" goto :eof
set _or_ip=%1
set _ip_right=%_or_ip:~-9%
:_trip_pre_zero
if "%_ip_right:~0,1%"=="0" if not "%_ip_right:~1,2%"=="" set "_ip_right=%_ip_right:~1%"&goto :_trip_pre_zero
if not defined _ip_right set _ip_right=0
set _ip_left=%_or_ip:~0,-9%
set /a _ip_right-=147483648
set /a _ip_left-=2
if %_ip_left% lss 2 goto :_iptrip_goon
if %_ip_left% equ 2 if %_ip_right% leq 147483647 goto :_iptrip_goon
set %~3=Error
goto :eof
:_iptrip_goon
::if %ip_right% lss 0 (set /a _ip_left-=1&set /a _ip_right+=1000000000)
set /a %~2=_ip_left*1000000000+_ip_right
set %~3=1
goto :eof
作者: netbenton
时间: 2009-1-3 18:28
标题: 回复:pooronce
我试了没有问题呀,贴上结果:
3.0.0.0 61.152.182.160 US
238.107.40.1 3.0.3.255 US
211.144.182.64 3.0.4.255 US
238.107.40.0 3.0.7.255 US
238.221.88.251 3.0.8.255 US
126.144.12.64 3.0.11.255 US
请按任意键继续. . .
作者: pooronce
时间: 2009-1-3 20:21
哦。。。贴错,试这个:
50331648 1033418400 US
3500000001 50332671 US
3949476416 50332927 US
3100000001 50333695 US
4207483643 4150333951 US
2123369536 50334719 US
借位与不借位的区别吧。。。
另外有两个数字落空,虽然机率很小,也得处理一下的
[
Last edited by pooronce on 2009-1-3 at 21:38 ]
作者: cz1314
时间: 2009-1-3 22:53
牛人啊!!谢谢 大侠门了!!佩服!!
作者: netbenton
时间: 2009-1-3 23:13
标题: 改进一下
@echo off
del IP_out.txt>nul
for /f "tokens=1,2,3" %%i in (ip.txt) do @call :output %%i %%j %%k
type IP_out.txt
pause&goto :eof
:output
set ip1=
set ip2=
call :ipconv "ip1" %1
call :ipconv "ip2" %2
echo %ip1% %ip2% %3>>IP_out.txt
goto :eof
:ipconv
rem 注意,此过程只能IP首位在127以下,即2147483647最大
if %~2 gtr 2147483646 (echo 数字太大,转呼过程2&call :ipconv2 %1 %2&goto :eof)
set ou=
:ipconv1
set varname=
set tmpIP=
set _IP_a=
set _IP_b=
set _IP_c=
set _IP_d=
set "varname=%~1"
set tmpIP=%2
set /a _IP_a=tmpIP^>^>24
if defined ou set /a _IP_a=_IP_a+128
set /a _IP_b=(tmpIP^>^>16)^&255
set /a _IP_c=(tmpIP^>^>8)^&255
set /a _ip_d=tmpIP^&255
set %varname%=%_IP_a%.%_IP_b%.%_IP_c%.%_IP_d%
goto :eof
:ipconv2
rem 增加此过程处理IP首位在127以上的代码
set var=%~2
set varf=%var:~0,-9%
rem ****** 去掉截串后前导 "0" 就可以了
set varb=1%var:~-9%-1000000000
rem ******
set /a varf=%varf%-2
set /a varb=%varb%-147483648
set /a var=%varf%*1000000000+%varb%
set ou=128
call :ipconv1 %~1 %var%
goto :eof
作者: netbenton
时间: 2009-1-3 23:31
标题: 换种算法看看
@echo off&setlocal enabledelayedexpansion
>IP_out.txt cd.
::此段采用 pooronce君 的代码
for /f "tokens=1,2,3" %%i in (ip.txt) do @call :output %%i %%j %%k
type IP_out.txt
pause&goto :eof
:output
set ip1=
set ip2=
call :ipconv "ip1" %1
call :ipconv "ip2" %2
echo %ip1% %ip2% %3>>IP_out.txt
goto :eof
::此段采用 pooronce君 的代码
:ipconv
set var=%~2
set vecho=
:agin
set varf=!var:~0,-6!
set varb=!var:~-6!
if defined varf (
set /a vs0=!varf!/256
set /a vy0=!varf!^%%256
set /a varb=!vy0!*1000000+4!varb!-4000000
)
set /a vs1=!varb!/256
set /a vy1=!varb!^%%256
if defined vecho (set vecho=!vy1!.!vecho!) else (set vecho=!vy1!)
set /a var=!vs0!*1000000+!vs1!
if not "!var!"=="0" goto :agin
set %~1=%vecho%
goto :eof
作者: pooronce
时间: 2009-1-4 11:02
不错不错,这个算法精简多了
建议右边部分取9位,这样尽量减少算法使用的时间
作者: cz1314
时间: 2009-1-4 14:09
标题: 看看这段如何??
@echo off&setlocal enabledelayedexpansion
set hex=0123456789ABCDEF
for /f "usebackq tokens=1,2*" %%i in ("ip.txt") do (
if not "%%i"=="" set var=&set h=&set s=%%i&call:lp
set/a ha=0x!var:~-8,2!,hb=0x!var:~-6,2!,hc=0x!var:~-4,2!,hd=0x!var:~-2,2!
set str1=!ha!.!hb!.!hc!.!hd!
if not "%%j"=="" set var=&set h=&set s=%%j&call:lp
set/a ha=0x!var:~-8,2!,hb=0x!var:~-6,2!,hc=0x!var:~-4,2!,hd=0x!var:~-2,2!
set str2=!ha!.!hb!.!hc!.!hd!
>>ip1.txt echo !str1! !str2! %%k
)
start "" "ip1.txt"
pause&goto :eof
:lp
set/a m=s/16,n=s%%16
set n=!hex:~%n%,1!
set h=%n%%h%
if %m% geq 16 set s=%m%&goto lp
set m=!hex:~%m%,1!
set var=0%m%%h%
看看 这样会不会 有什么问题呢?
[
Last edited by cz1314 on 2009-1-4 at 14:12 ]
作者: HAT
时间: 2009-1-4 14:48
标题: Re 17楼
有没有问题,你自己测试一下不就知道了么?
作者: linee
时间: 2009-1-5 14:47
我也来练习一下,
@echo off
for /f "tokens=1,2,3" %%i in (test.txt) do call :conv %%i&call :conv %%j&echo %%k
goto :EOF
:conv
set/a ip=%1,ip1_=0
if %ip% lss 0 set/a ip=ip+2147483647+1,ip1_+=128
set/a ip1=ip/16777216,ip-=ip1*16777216,ip1+=ip1_
set/a ip2=ip/65536,ip-=ip2*65536
set/a ip3=ip/256,ip-=ip3*256
set /p =IP,%1 %ip1%.%ip2%.%ip3%.%ip% <nul
作者: netbenton
时间: 2009-1-6 02:07
哇,厉害!
作者: terse
时间: 2009-1-6 12:05
19楼上改进
@echo off&setlocal enabledelayedexpansion
cd.>ip1.txt
for /f "tokens=1,2,3" %%i in (ip.txt) do (
set n=0
call:lp %%i %%j
>>ip1.txt echo !str1! !str2! %%k
)
pause&goto :eof
:lp
set/a ip=%1,n+=1
if %ip% lss 0 (set/a ip-=2147483648,_ip=128)else set _ip=0
set/a ip1=ip/16777216,ip2=ip%%16777216/65536,ip3=ip%%65536/256,ip4=ip%%256,ip1+=_ip
set "str%n%=%ip1%.%ip2%.%ip3%.%ip4%"
if not "%2" == "" call:lp %2
作者: linee
时间: 2009-1-6 20:57
位移版,似乎更简单点
@echo off
for /f "tokens=1,2,3" %%i in (test.txt)do call:conv %%i&call:conv %%j&echo %%k
goto:EOF
:conv
for %%i in (24 16 8 0)do set/a ip%%i=%1^>^>%%i^&255
set /p=IP,%1 %ip24%.%ip16%.%ip8%.%ip0% <nul
[
Last edited by linee on 2009-1-6 at 21:06 ]
作者: netbenton
时间: 2009-1-7 02:53
22楼的应该是绝版了
偶学习了
[
Last edited by netbenton on 2009-1-7 at 02:54 ]
作者: cz1314
时间: 2009-1-8 00:34
22 楼 好象没有输出大批文本啊。。。
作者: netbenton
时间: 2009-1-8 01:06
标题: 根据22楼的稍作改动,这样就合要求了
@echo off
>IP_out.txt cd.
for /f "tokens=1,2,3" %%i in (ip.txt)do call:conv %%i&call:conv %%j&echo %%k >>IP_out.txt
type IP_out.txt
pause
goto:EOF
:conv
for %%i in (24 16 8 0)do set/a ip%%i=%1^>^>%%i^&255
set /p= %ip24%.%ip16%.%ip8%.%ip0% <nul >>IP_out.txt
[
Last edited by netbenton on 2009-1-8 at 01:12 ]
作者: scriptor
时间: 2009-1-15 21:27
Quote: |
Originally posted by netbenton at 2009-1-8 01:06:
@echo off
>IP_out.txt cd.
for /f "tokens=1,2,3" %%i in (ip.txt)do call:conv %%i&call:conv %%j&echo %%k >>IP_out.txt
type IP_out.txt
pause
goto:EOF
:conv
for %%i ... |
|
22# 25# 似乎都对超过4294967295 的数字不能转换了.
这是32bit机器上的上限.
作者: scriptor
时间: 2009-1-15 21:30
并且, 对于超出范围的数据,比如:
50331648 1033418400 US
4000000001 50332671 US
3549476416 50332927 US
4000000000 50333695 US
4007483643 50333951 US
11111111111 11111111110 cn
2123369536 50334719 US
4294967295 4294967294 us
11111111111 11111111110 cn
输出结果会取用上一个有效数据的值.
作者: exzzz
时间: 2009-1-15 22:31
牛人啊!顶一个,最近几天忙着培训,没时间来学习了,呵呵。
作者: netbenton
时间: 2009-1-16 00:30
超过32位的可以分成两截来处理,如15楼的方法,
只是不知道超过32位的ip地址有什么用?
3.0.0.0 61.152.182.160 US
238.107.40.1 3.0.3.255 US
211.144.182.64 3.0.4.255 US
238.107.40.0 3.0.7.255 US
238.221.88.251 3.0.8.255 US
2.150.70.25.199 2.150.70.25.198 cn
126.144.12.64 3.0.11.255 US
255.255.255.255 255.255.255.254 us
2.150.70.25.199 2.150.70.25.198 cn
作者: cz1314
时间: 2009-1-16 01:37
netbenton
非常感谢!也感谢所有老师的帮助!