Board logo

标题: [文本处理] [已解决]批处理怎样对手机号码归属地数据进行筛选? [打印本页]

作者: jack1505    时间: 2010-5-5 10:40     标题: [已解决]批处理怎样对手机号码归属地数据进行筛选?

数据下载(更新了地址及quhao.txt)
http://www.rayfile.com/files/bd808cca-58db-11df-98b5-0015c55db73d/

说明:
1.第一个原始数据文件data.txt内含有20万条数据(中间以tab分隔),文件大小超过8MB
2.第二个quhao.txt文件有300多条数据(中间以空格分隔),文件大小不到5KB

==============================================================================
1.原始数据
手上有一个比较详尽的手机号码归属地数据文件data.txt,格式如下(中间以tab分隔)
1534960 宁夏银川 电信CDMA卡
1534961 宁夏银川 电信CDMA卡
1534967 宁夏银川 电信CDMA卡
1534968 宁夏银川 电信CDMA卡
1534969 宁夏银川 电信CDMA卡
1534970 青海西宁 电信CDMA卡
1534971 青海西宁 电信CDMA卡
1534972 青海西宁 电信CDMA卡
1534973 青海西宁 电信CDMA卡
1534974 青海西宁 电信CDMA卡
1534975 青海海东 电信CDMA卡
1534976 青海海东 电信CDMA卡
1534977 青海海西 电信CDMA卡
1534978 青海共和 电信CDMA卡
1534979 青海格尔木 电信CDMA卡
1534985 安徽巢湖 电信CDMA卡
1534986 安徽六安 电信CDMA卡
1534987 安徽六安 电信CDMA卡
多数为三段(多数号码是连续的,前后仅相差1,但部分号码不是连续的)

1566023 广东佛山 联通 GSM卡
1864353 吉林通化 联通WCDMA 3G卡
1881943 广东广州 移动TD-SCDMA 3G卡
1892413 广东广州 电信天翼  3G卡
部分数据为四段数据


2.数据精简
预将上述数据中,归属地相同的连续号码,精简为号段形式,并删掉手机卡类型,输出格式如下:
1534960 宁夏银川
1534962 未知
1534967 宁夏银川
1534970 青海西宁
1534975 青海海东
1534977 青海海西
1534978 青海共和
1534979 青海格尔木
1534980 未知
1534985 安徽巢湖
1534986 安徽六安

精简的目的就是极大地减小数据量,仅表示该号段第一个号码,所有大于第一个号码的均视为同一个归属地
解释为:1534960~1534961 宁夏银川,1534962~1534966 未知1534967~1534969 宁夏银川,1534970~1534974 青海西宁……

data.txt中多数号码是连续的,前后仅相差1
但部分不是连续的号码,应增加一行内容为“最后一个连续号码+1 空格 未知”,见增加的蓝色内容

如:1534961、1534963、1534967不是连续的,因此应增加“1534961+1 空格 未知”,即“1534962 未知
       若不加“1534962 未知”,则会误认为1534962与1534961归属相同




3.更改归属地名称为区号代码
另有一个quhao.txt文件,格式如下(中间以空格分隔)
111 未知
564 安徽六安
565 安徽巢湖
951 宁夏银川
971 青海西宁
972 青海海东
977 青海海西
979 青海格尔木

将刚才第二步精简后的数据中,参考quhao.txt,将对应的归属地名称改为区号代码,最终输出格式如下(中间以空格分隔)
1534960 951
1534962 111
1534967 951
1534970 971
1534975 972
1534977 977
1534978
1534979 979
1534980 111
1534985 565
1534986 564

quhao.txt中没有1534978对应的“青海共和”,所以后面为空(便于今后补充)


4.结果输出
如果最后结果文件大小不到5KB,显然把所有归属相同的都精简了,每个地区只剩一个号段了
最终结果文件大小应该超过600KB才合理


结果应该是这种格式(从小到大排列)
1300000 10
1300001 519
1300002 565
1300003 111
1300006 25
1300007 111
1300008 27
1300009 111
1300010 10
1300012 22
1300015 533
1300016 535
1300017 531
1300018 22
1300020 21
1300025 25
1300027 535
1300028 25
1300033 510
1300040 20
1300045 10

data20100506.rar 于 2010-5-6 14:48  更新
http://pan.baidu.com/share/link?shareid=4185092398&uk=1124163200
作者: jack1505    时间: 2010-5-5 10:48     标题: 感谢帮助过我的热心新

没想到在批处理之家有这么多的热心人,在这里对所有帮助过我的人表示由衷的谢意!

按出场顺序排列:
CUer
yangfengoo
hanyeguxing
netbenton版主
namejm管理员
随风 超级版主
qzwqzw
neorobin
Batcher管理员



感谢CUer,不计其数的帮我完善代码,最终运行成功!
netbenton版主的第一版代码除了没有“未知”地外,结果也正确,速度很快
namejm管理员、随风 超级版主的第一版代码为了满足我显示过程的要求,速度稍慢
yangfengoo、hanyeguxing、qzwqzw也为我编写并修改了代码



再次谢谢!

[ 本帖最后由 jack1505 于 2010-5-7 11:04 编辑 ]
作者: CUer    时间: 2010-5-5 11:41

  1. gawk "!($2 in a){a[$2];$3=\"\";print}" yuanshi.txt >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR{print a[$2],$1}" jingjian.txt quhao.txt >result.txt
复制代码

作者: yangfengoo    时间: 2010-5-5 11:58

  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "tokens=1,2" %%a in (quhao.txt) do set #%%b=%%a
  3. (for /f "tokens=1,2" %%a in (data.txt) do echo.%%a !#%%b!)>>结果.txt
复制代码
9M测试不到1分钟
作者: jack1505    时间: 2010-5-5 12:01

谢谢二楼高手的相助!
试了一下,输出的jingjian.txt和result.txt都是空的

单独运行第一行代码输出的jingjian.txt也是空的
作者: jack1505    时间: 2010-5-5 12:12

三楼的代码没有对数据进行精简吧?
而且两个文件的分隔符不同,tab和空格,这个有影响吗?

我测试后输出结果为空
作者: CUer    时间: 2010-5-5 12:14

C:\Test>gawk "!($2 in a){a[$2];$3=\"\";print}" yuanshi.txt >jingjian.txt

C:\Test>gawk "NR==FNR{a[$2]=$1}NR>FNR{print a[$2],$1}" jingjian.txt quhao.txt >result.txt

C:\Test>type result.txt
1354910 753
1354920 769
1354950 735
1354960 736
1354964 731

C:\Test>gawk --version
GNU Awk 3.1.6
Copyright (C) 1989, 1991-2007 Free Software Foundation.
作者: yangfengoo    时间: 2010-5-5 12:31

原帖由 jack1505 于 2010-5-5 12:12 发表
三楼的代码没有对数据进行精简吧?
而且两个文件的分隔符不同,tab和空格,这个有影响吗?

我测试后输出结果为空


我直接复制的,第一和二个都是空格分割。
作者: yangfengoo    时间: 2010-5-5 12:36

tab,空格分割兼容
  1. @echo off&setlocal enabledelayedexpansion
  2. echo.%time%
  3. for /f "tokens=1,2" %%a in (quhao.txt) do set #%%b=%%a
  4. (for /f "tokens=1,2 delims=  " %%a in (data.txt) do echo.%%a !#%%b!)>>结果.txt
  5. echo.%time%
  6. pause
复制代码

[ 本帖最后由 yangfengoo 于 2010-5-5 12:37 编辑 ]
作者: yangfengoo    时间: 2010-5-5 12:42

注意 delims=
后面是一个tab键和一个空格键  直接复制代码不行,论坛对tab键做了处理
作者: jack1505    时间: 2010-5-5 12:45

原帖由 CUer 于 2010-5-5 12:14 发表
C:\Test>gawk "!($2 in a){a[$2];$3=\"\";print}" yuanshi.txt >jingjian.txt

C:\Test>gawk "NR==FNR{a[$2]=$1}NR>FNR{print a[$2],$1}" jingjian.txt quhao.txt >result.txt

C:\Test>type result.txt
135491 ...


再次感谢!刚才是因为缺少gawk.exe,所以输出为空

但现在运行又有新问题了,提示
Invalid keyboard code specified
Program too big to fit in memory

增加运行smartdrv也不行啊
作者: CUer    时间: 2010-5-5 12:55

你的gawk版本是多少?
在gawk上面加一句chcp 936行吗?
在gawk上面加一句chcp 437行吗?
作者: jack1505    时间: 2010-5-5 13:00

原帖由 CUer 于 2010-5-5 12:55 发表
你的gawk版本是多少?
在gawk上面加一句chcp 936行吗?
在gawk上面加一句chcp 437行吗?


刚才下了新版本,可以输出了,不为空
但结果不对

jingjian.txt内容只有一行
1300000 北京ഠ
结尾是一个黑色方块

result.txt内容只有区号,没有手机号段
10
20
21
22
23
24
25
27
28
298
293
310
311
312
313
314
315
316
317

均为:空格+区号

======================================
是不是Tab和空格没有区分的原因?

[ 本帖最后由 jack1505 于 2010-5-5 14:20 编辑 ]
作者: jack1505    时间: 2010-5-5 13:05     标题: 回复yangfengoo

改为delims= tab空格
输出依然为空,怎么回事呢?

echo.%time%只是显示时间,不是显示进度(这个功能没有也罢)
作者: hanyeguxing    时间: 2010-5-5 13:52

按电话区号分组排列手机区段:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "tokens=1,2" %%a in (data.txt) do (if not "%%b"=="!b!" set @%%b@%%a=a
  3. echo.正在预处理%%a %%b&set b=%%b)
  4. echo.正在进行后期处理...
  5. for /f "tokens=1,2" %%a in (quhao.txt) do set @%%b#%%a=b
  6. (for /f "tokens=2,3 delims==@#" %%a in ('set @') do if %%b==b (set a=%%a) else echo.%%a !a!)>结果.txt
  7. echo.已经完成&pause
复制代码
如果想加快处理速度,不看到处理过程,则:
  1. @echo off&setlocal enabledelayedexpansion&echo.正在处理中。。。
  2. for /f "tokens=1,2" %%a in (data.txt) do (if not "%%b"=="!b!" set @%%b@%%a=a
  3. set b=%%b)
  4. for /f "tokens=1,2" %%a in (quhao.txt) do set @%%b#%%a=b
  5. (for /f "tokens=2,3 delims==@#" %%a in ('set @') do if %%b==b (set a=%%a) else echo.%%a !a!)>结果.txt
复制代码

[ 本帖最后由 hanyeguxing 于 2010-5-5 17:47 编辑 ]
作者: jack1505    时间: 2010-5-5 14:09     标题: 回复15楼hanyeguxing

直接运行后,结果.txt不为空
但没有手机号段,只有区号

如:
10
20
21
22
23
24
25
27
28
数字前面只有一个空格
作者: jack1505    时间: 2010-5-5 14:13

根据3楼CUer和15楼hanyeguxing的代码
输出结果都相同,均为:空格+区号

此结果相当于将quhao.txt中的归属地删除,并与区号做了调换
并没有对原始数据进行精简和替换

不过还是要谢谢各位热心人!!
作者: CUer    时间: 2010-5-5 14:18

  1. gawk -F"\t" "!($2 in a){a[$2];$3=\"\";print}" yuanshi.txt >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR{print a[$2],$1}" jingjian.txt quhao.txt >result.txt
复制代码

作者: hanyeguxing    时间: 2010-5-5 14:20     标题: 回复 16楼 的帖子

你是直接运行我在15楼的代码,没做任何修改?
作者: jack1505    时间: 2010-5-5 14:28

原帖由 CUer 于 2010-5-5 14:18 发表
gawk -F"\t" "!($2 in a){a[$2];$3=\"\";print}" yuanshi.txt >jingjian.txt
gawk "NR==FNR{a[$2]=$1}NR>FNR{print a[$2],$1}" jingjian.txt quhao.txt >result.txt


如果这么改,输出都为空了!

各位这么帮我,我都不好意思,惭愧啊~
作者: jack1505    时间: 2010-5-5 14:30

原帖由 hanyeguxing 于 2010-5-5 14:20 发表
你是直接运行我在15楼的代码,没做任何修改?


我是直接复制的,未作任何改动,运行后结果如我刚才所说:只有空格+区号
作者: CUer    时间: 2010-5-5 14:32

  1. gawk -F"[ \t]" "!($2 in a){a[$2];$3=\"\";print}" yuanshi.txt >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR{print a[$2],$1}" jingjian.txt quhao.txt >result.txt
复制代码

作者: hanyeguxing    时间: 2010-5-5 14:42

1,检查data.txt和quhao.txt的文件名是否正确
2,提供两个文本的编码分别是什么?
或者运行下面这个批处理测试:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "tokens=1,2" %%a in (data.txt) do set "#data=%%a %%b"
  3. for /f "tokens=1,2" %%a in (quhao.txt) do set "#quhao=%%a %%b"
  4. echo.测试结果:
  5. set #
  6. pause
复制代码
并说明最后显示什么?

[ 本帖最后由 hanyeguxing 于 2010-5-5 14:45 编辑 ]
作者: jack1505    时间: 2010-5-5 14:47     标题: 回复22楼CUer和23楼hanyeguxing

回复22楼CUer
修改后的代码和第一次的结果一样

回复23楼hanyeguxing
我把原始数据上传了,本论坛限制太多
http://cachefile25.rayfile.com/z ... 264658513d/data.rar
http://www.rayfile.com/files/a78 ... -935b-0015c55db73d/
作者: hanyeguxing    时间: 2010-5-5 14:58

新建一个文本,命令为临时.txt。
然后打开data.txt,全选并复制里面所有内容,在临时.txt里粘贴。
保存后,删除data.txt,并把临时.txt改名为data.txt
然后再运行我在15楼的代码

[ 本帖最后由 hanyeguxing 于 2010-5-5 15:02 编辑 ]
作者: jack1505    时间: 2010-5-5 15:30

原帖由 hanyeguxing 于 2010-5-5 14:58 发表
新建一个文本,命令为临时.txt。
然后打开data.txt,全选并复制里面所有内容,在临时.txt里粘贴。
保存后,删除data.txt,并把临时.txt改名为data.txt
然后再运行我在15楼的代码


谢谢,终于有结果了!
看来是txt格式问题,让诸位辛苦了!深表歉意!
1楼、15楼、18楼的代码均可

新问题1:
1566023 广东佛山 联通 GSM卡
1864353 吉林通化 联通WCDMA 3G卡
1881943 广东广州 移动TD-SCDMA 3G卡
1892413 广东广州 电信天翼  3G卡

以上格式数据有四段数据,最后一段没有删除,造成输出有误

新问题2:
最后结果文件大小不到5KB,显然把所有归属相同的都精简了,每个地区只剩一个号段了
应该将归属地相同的连续号段进行精简
如1331000 至1331019都是上海,保留1331000即可
而往下1351210至1351219还是上海,同理保留1351210

最终结果文件大小应该超过500KB才合理
作者: hanyeguxing    时间: 2010-5-5 17:10

按电话区号分组排列手机区段:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "tokens=1,2" %%a in (data.txt) do (if not "%%b"=="!b!" set @%%b@%%a=a
  3. echo.正在预处理%%a %%b&set b=%%b)
  4. echo.正在进行后期处理...
  5. for /f "tokens=1,2" %%a in (quhao.txt) do set @%%b#%%a=b
  6. (for /f "tokens=2,3 delims==@#" %%a in ('set @') do if %%b==b (set a=%%a) else echo.%%a !a!)>结果.txt
  7. echo.已经完成&pause
复制代码
如果想加快处理速度,不看到处理过程,则:
  1. @echo off&setlocal enabledelayedexpansion&echo.正在处理中。。。
  2. for /f "tokens=1,2" %%a in (data.txt) do (if not "%%b"=="!b!" set @%%b@%%a=a
  3. set b=%%b)
  4. for /f "tokens=1,2" %%a in (quhao.txt) do set @%%b#%%a=b
  5. (for /f "tokens=2,3 delims==@#" %%a in ('set @') do if %%b==b (set a=%%a) else echo.%%a !a!)>结果.txt
复制代码

[ 本帖最后由 hanyeguxing 于 2010-5-5 17:36 编辑 ]
作者: Batcher    时间: 2010-5-5 17:40     标题: 回复 26楼 的帖子

请把这些信息全部更新到顶楼,以便他人查看。
作者: jack1505    时间: 2010-5-5 18:04

原帖由 hanyeguxing 于 2010-5-5 17:10 发表
按电话区号分组排列手机区段:@echo off&setlocal enabledelayedexpansion
for /f "tokens=1,2" %%a in (data.txt) do (if not "%%b"=="!b!" set @%%b@%%a=a
echo.正在预处理%%a %%b&set b=%%b)
echo.正在进行后期 ...


谢谢,处理花了半个小时

最终结果已经非常接近了!但结果数据不是从小到大连续排列的,因此号段无效
输出的手机号码必须从小到大连续排列,而后面的区号顺序无所谓

如:
1300000 10
1300001 519
1300006 25
1300010 10
1300012 22
1300015 533
1300016 535
1300017 531
1300018 22
1300020 21
1300025 25
1300027 535
1300028 25
1300033 510
1300040 20
1300045 10
1300050 20
1300061 724
1300062 20
1300065 536
1300066 20
1300067 577
1300068 20
1300069 771
1300070 20

[ 本帖最后由 jack1505 于 2010-5-5 22:29 编辑 ]
作者: CUer    时间: 2010-5-5 21:26

  1. gawk -F" \t" "($1!=p+1)||(!($2 in a)){a[$2];print $1,$2}{p=$1}" data.txt >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR{print a[$2],$1}" jingjian.txt quhao.txt >result.txt
复制代码

作者: jack1505    时间: 2010-5-5 22:17

原帖由 CUer 于 2010-5-5 21:26 发表
gawk -F"\t" "($1!=p+1)||(!($2 in a)){a[$2];print $1,$2}{p=$1}" data.txt >jingjian.txt
gawk "NR==FNR{a[$2]=$1}NR>FNR{print a[$2],$1}" jingjian.txt quhao.txt >result.txt


回复30楼:纠正一下,运行后jingjian.txt和data.txt完全一样,而result.txt与之前的几段代码结果相同

[ 本帖最后由 jack1505 于 2010-5-5 22:51 编辑 ]
作者: CUer    时间: 2010-5-5 22:26

你是不是把\t前面的空格丢掉了?
作者: jack1505    时间: 2010-5-5 22:39

原帖由 CUer 于 2010-5-5 22:26 发表
你是不是把\t前面的空格丢掉了?


没有去掉空格,完全是复制粘贴过去的
论坛中的引用会再次省略一些符合,所以没了空格

30楼的代码运行后很奇怪,jingjian.txt变成与data.txt一样的文件了

其实我很期待gawk的处理速度,hanyeguxing的代码已经能输出非常接近的结果了,只是速度慢

[ 本帖最后由 jack1505 于 2010-5-5 22:52 编辑 ]
作者: CUer    时间: 2010-5-5 23:08

  1. type data.txt | gawk -F"[ \t]" "($1!=p+1)||(!($2 in a)){a[$2];print $1,$2}{p=$1}" >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR&&($2 in a){print a[$2],$1}" jingjian.txt quhao.txt >result.txt
复制代码

作者: jack1505    时间: 2010-5-5 23:18

原帖由 CUer 于 2010-5-5 23:08 发表
type data.txt | gawk -F"[ \t]" "($1!=p+1)||(!($2 in a)){a[$2];print $1,$2}{p=$1}" >jingjian.txt
gawk "NR==FNR{a[$2]=$1}NR>FNR&&($2 in a){print a[$2],$1}" jingjian.txt quhao.txt >result.txt


这么晚还没睡啊!感动ing……

说实话非常感谢CUer和hanyeguxing两位大力的帮助,虽然没有成功,但已经很接近了

麻烦CUer仔细看一下我修改补充的1楼的帖子,应该说的很详细了
最后的结果应该是从小到大连续排列的,并且文件大于500KB
作者: CUer    时间: 2010-5-5 23:45

  1. type data.txt | gawk -F"[ \t]" "($1!=p+1)||(!($2 in a)){a[$2];print $1,$2}{p=$1}" >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR&&($2 in a){print $1,a[$2]}" quhao.txt jingjian.txt >result.txt
复制代码
不知道你为什么认为大于500KB才正常,我这个代码得到的结果大于9KB,你能否帮忙指出哪行数据丢掉了?
作者: netbenton    时间: 2010-5-6 00:08

先排序data.txt到data1.txt
再把quhao.txt的内容定义到变量
最后读data1.txt取同区的第一个显示出来
注意:用for /f 命令处理文本时,默认是以空格和[Tab]同时作为字段分隔符的
  1. @echo off&setlocal enabledelayedexpansion
  2. sort data.txt /o data1.txt
  3. for /f "tokens=1-2" %%a in (quhao.txt) do set %%b=%%a
  4. (
  5. for /f "tokens=1-2" %%a in (data1.txt) do (
  6.     if "!var!" neq "%%b" (
  7.         echo;%%a !%%b!
  8.         set var=%%b
  9. ))
  10. )>结果.txt
复制代码

[ 本帖最后由 netbenton 于 2010-5-6 00:13 编辑 ]
作者: jack1505    时间: 2010-5-6 00:23     标题: 回复36楼CUer

首先,jingjian.txt和result.txt的行数应该一直,因为result.txt只是替换了区号代码

其次,经我输出测试对比jingjian.txt和data.txt
发现第11行就少了这些数据:
1300025        江苏南京
1300027        山东烟台
1300028        江苏南京

另外,文件大于500KB是有依据的(手机号码从1300000~1899999,除部分地区外,基本每个地区10行,quhao.txt中共有336个地区)
hanyeguxing的代码已经可以正确精简数据了,只是输出顺序有误、速度慢,其结果为633KB
作者: CUer    时间: 2010-5-6 00:32

  1. type data.txt | gawk -F"[ \t]" "($1!=p1+1)||(p2!=$2){a[$2];print $1,$2}{p1=$1;p2=$2}" >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR&&($2 in a){print $1,a[$2]}" quhao.txt jingjian.txt >result.txt
复制代码
这样可以得到大于500KB的文件,你把这个结果跟37楼大于600KB的比较一下,看看到底需要哪个。
作者: jack1505    时间: 2010-5-6 00:36

原帖由 netbenton 于 2010-5-6 00:08 发表
先排序data.txt到data1.txt
再把quhao.txt的内容定义到变量
最后读data1.txt取同区的第一个显示出来
注意:用for /f 命令处理文本时,默认是以空格和[Tab]同时作为字段分隔符的
@echo off&setlocal enabledelaye ...


37楼netbenton版主正解!
输出正确、速度较快,要说完美只差不能显示进度(但也不影响使用)

原始数据data.txt本身就是从小到大连续排列的,不需要再排序了
可以精简sort命令行,提高速度!

非常感谢“批处理之家”的热心高手,这里氛围真好!
作者: CUer    时间: 2010-5-6 00:37

如果要求jingjian.txt和result.txt行数一样的话(50046行),可以这样做:
  1. type data.txt | gawk -F"[ \t]" "($1!=p1+1)||(p2!=$2){a[$2];print $1,$2}{p1=$1;p2=$2}" >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR{if($2 in a)print $1,a[$2];else print $1}" quhao.txt jingjian.txt >result.txt
复制代码

作者: namejm    时间: 2010-5-6 00:38

  我的思路与37楼netbenton不谋而合,耗时约1分钟,结果应该是50023条记录,619.5K大小,不过貌似部分号段在quhao.txt中没有对应的区域,处理结果请看附件,不知道和楼主所要的结果有何差别。

  要想看到处理进程,请用这个代码:
  1. @echo off
  2. set t=%time%
  3. for /f "tokens=1,2" %%i in (quhao.txt) do set %%j=%%i
  4. setlocal enabledelayedexpansion
  5. (for /f "tokens=1,2" %%i in (data.txt) do (
  6.     echo %%i %%j>con
  7.     if not "%%j"=="!address!" (
  8.         echo %%i !%%j!
  9.         set address=%%j
  10.     )
  11. ))>result.txt
  12. start result.txt
  13. echo %t%
  14. echo %time%
  15. pause
复制代码

作者: CUer    时间: 2010-5-6 00:39

37楼得到的结果是50023行,41楼得到的结果是50046行,到底哪个是正确的?
作者: CUer    时间: 2010-5-6 00:45

41楼比37楼多出如下行:
1349320 10
1349380 10
1349740 10
1349970 10
1380050
1380062 592
1534346 354
1534666
1534967 951
1535255 999
1536280 769
1536380 757
1536545 516
1555950 595
1572220 22
1860100 10
1861800 10
1863900 371
1879637 516
1880944 931
1881100 10
1887888 771
1893893 755

根据楼主的规则,这些行是需要保留下来的吗?
作者: jack1505    时间: 2010-5-6 00:50     标题: 回复44楼

多出的数据应该无用

因为这些数据前后虽然不是相差1,但归属均相同,也可视为连续的数据

比如多出的“1349320”,前面的“1349299”和后面的“1349321”均为相同归属地“北京”

[ 本帖最后由 jack1505 于 2010-5-6 01:14 编辑 ]
作者: 随风    时间: 2010-5-6 03:04

42楼namejm似乎漏掉了个sort, 若原始文件未经排序则会结果错误
这个题好像只有这个思路是最高效的了
只是不知道 if defined 和 if "a"=="b" 到底谁更快
只知道在海量数据中 set a=要比set "a="快,引号或多或少会对效率有点影响吧?
  1. @echo off
  2. for /f "tokens=1,2" %%i in (quhao.txt) do set %%j=%%i
  3. setlocal enabledelayedexpansion
  4. (for /f "tokens=1,2" %%i in (data.txt) do (
  5.    echo %%i %%j>con
  6.    if defined %%j echo %%i !%%j!&set %%j=
  7. ))>result.txt
  8. sort result.txt /o result2.txt&rem 若原始文件本身就以排好序则不需这一句。
  9. start result2.txt
复制代码

作者: qzwqzw    时间: 2010-5-6 09:47

麻烦谁把楼主的数据文件给我邮箱里发一份
顶楼的链接我这里访问不到
作者: CUer    时间: 2010-5-6 09:56     标题: 回复 45楼 的帖子

这跟你顶楼的描述不是冲突了吗?你的要求到底是怎样的呢?
应该将归属地相同连续号段进行精简
如1331000 至1331019都是上海,保留1331000即可
而往下1351210至1351219还是上海,同理保留1351210

作者: jack1505    时间: 2010-5-6 10:20

原帖由 CUer 于 2010-5-6 09:56 发表
这跟你顶楼的描述不是冲突了吗?你的要求到底是怎样的呢?



谢谢一如既往的关注,我修改了顶楼的说明,这次应该能说明白
作者: 随风    时间: 2010-5-6 14:29     标题: 回复 47楼 的帖子

已帮楼主把数据上传到顶楼
作者: jack1505    时间: 2010-5-6 14:48

原帖由 随风 于 2010-5-6 14:29 发表
已帮楼主把数据上传到顶楼


谢谢版主,但是我把data.txt和quhao.txt更新了
可惜权限不够,无法编辑
作者: qzwqzw    时间: 2010-5-6 17:48     标题: 回复 42楼 的帖子

46楼的代码存在楼主所说的
一个地区一个号段的问题
算法与42楼存在本质的不同

42楼的代码有几个问题

setlocal的位置不知为何放在for之后
但是如果在命令行环境中执行此代码
将使cmd的当前会话产生大量临时变量
这显然违背了程序的设计原则

echo %%i %%j>con
应该是显示进度的
但正是它严重影响力程序的性能
去掉它运行速度可以提高十几倍
所以不如去掉
  1. @echo off & setlocal enabledelayedexpansion
  2. set t=%time%
  3. for /f "tokens=1,2" %%i in (quhao.txt) do set %%j=%%i
  4. (for /f "tokens=1,2" %%i in (data.txt) do (
  5.     if not "%%j"=="!address!" (
  6.         echo %%i !%%j!
  7.         set address=%%j
  8.     )
  9. ))>result.txt
  10. echo 起始时间:%t%
  11. echo 终止时间:%time%
  12. pause
  13. start result.txt
复制代码

作者: jack1505    时间: 2010-5-6 18:09     标题: 回复52楼qzwqzw

感谢了,你的代码测试后,没问题
目前你和37楼的结果正确

42楼和46楼都增加了进度显示,确实速度大大降低
看来你的做法,加上起止的时间较为方便

不过我一楼补充了内容,这个没有实现,详见一楼第2条

[ 本帖最后由 jack1505 于 2010-5-6 18:11 编辑 ]
作者: qzwqzw    时间: 2010-5-6 18:44     标题: 回复 53楼 的帖子

按照新要求重新写了代码
急就章之作请多做测试
因为不确定连续同一地区的多个号码段中是否存在未知号码段
所以对数据中的每个号码段都做了之前是否存在未知号码段的判定
因此代码运行时间增加为3倍左右
  1. @echo off & setlocal enabledelayedexpansion
  2. set t=%time%
  3. for /f "tokens=1,2" %%i in (quhao.txt) do set %%j=%%i
  4. set nextnum=1300000
  5. (for /f "tokens=1,2" %%i in (data.txt) do (
  6.     if %%i neq !nextnum! (
  7. echo !nextnum! 111
  8. set area=未知
  9. )
  10.     if not "%%j"=="!area!" (
  11.         echo %%i !%%j!
  12.         set area=%%j
  13.     )
  14. set /a nextnum=%%i+1
  15. ))>result.txt
  16. echo 起始时间:%t%
  17. echo 终止时间:%time%
  18. pause
  19. start result.txt
复制代码

[ 本帖最后由 qzwqzw 于 2010-5-6 18:47 编辑 ]
作者: netbenton    时间: 2010-5-6 19:48

1,如果号码不是连续的增加一个未知项
2,如果区域在quhao.txt中不存在,转为未知项
  1. @echo off&setlocal enabledelayedexpansion
  2. sort data.txt /o data1.txt
  3. for /f "tokens=1-2" %%a in (quhao.txt) do set %%b=%%a
  4. ::\\取第一个电话号码
  5. set /p num=<data1.txt
  6. set /a num=num
  7. ::\\\\\\\
  8. (
  9. for /f "tokens=1-2" %%a in (data1.txt) do (
  10.     if "!var!" neq "%%b" (
  11.         if !num! neq %%a echo; !num! !未知!
  12.         if #!%%b! equ # (echo;%%a !未知!) else echo;%%a !%%b!
  13.         set var=%%b
  14. ) else (set /a num=%%a+1)
  15. )
  16. )>结果.txt
复制代码

作者: neorobin    时间: 2010-5-6 21:17     标题: RE: 55

测试了下,结果最前面的几行为
1300000 10
1300000 111
1300001 519
1300000 111
1300002 565
1300000 111
1300006 25
1300000 111
1300008 27
1300000 111
1300010 10

与 LZ 在顶楼的要求是不符的:
1300000 10
1300001 519
1300002 565
1300003 111
1300006 25
1300007 111
1300008 27
1300009 111

作者: netbenton    时间: 2010-5-6 21:32

改成这样应该可以了
  1. @echo off&setlocal enabledelayedexpansion
  2. sort data.txt /o data1.txt
  3. for /f "tokens=1-2" %%a in (quhao.txt) do set %%b=%%a
  4. ::\\取第一个电话号码
  5. set /p num=<data1.txt
  6. set /a num=num
  7. ::\\\\\\\
  8. (
  9. for /f "tokens=1-2" %%a in (data1.txt) do (
  10.     if "!var!" neq "%%b" (
  11.         if !num! neq %%a echo;!num! !未知!
  12.         if #!%%b! equ # (echo;%%a !未知!) else echo;%%a !%%b!
  13.         set var=%%b
  14.     )
  15. set /a num=%%a+1
  16. )
  17. )>结果.txt
复制代码

[ 本帖最后由 netbenton 于 2010-5-6 21:38 编辑 ]
作者: Batcher    时间: 2010-5-6 23:07     标题: 回复 57楼 的帖子

楼主不是说1534978后面应该为空么,但你的结果里面对应的是111。
作者: CUer    时间: 2010-5-6 23:37

  1. type data.txt | gawk -F"[ \t]" "(NR!=1)&&($1!=p1+1){print p1+1\" 未知\"}($1!=p1+1)||(p2!=$2){print $1,$2}{p1=$1;p2=$2}" >jingjian.txt
  2. gawk "NR==FNR{a[$2]=$1}NR>FNR{if($2 in a)print $1,a[$2];else print $1}" quhao.txt jingjian.txt >result.txt
复制代码
57楼得到的结果是50641行
我的代码得到和54楼得到的结果一样都是50679行
作者: jack1505    时间: 2010-5-6 23:43     标题: 回复59楼

这次代码运行没问题,结果也正确
尤其体现出gawk命令的速度优势

谢谢!!!

[ 本帖最后由 jack1505 于 2010-5-6 23:58 编辑 ]
作者: neorobin    时间: 2010-5-8 00:06     标题: RE: 59

57楼代码稍作修改后, 可输出地区连续但号段不连续的断点, 输出结果去掉所有尾部的 空格111 后将与 CUer 的 gawk 版的结果完全一致:
  1. @echo off&setlocal enabledelayedexpansion
  2. sort data.txt /o data1.txt
  3. for /f "tokens=1-2" %%a in (quhao.txt) do set %%b=%%a
  4. ::\\取第一个电话号码
  5. set /p num=<data1.txt
  6. set /a num=num
  7. ::\\\\\\\
  8. (
  9. for /f "tokens=1-2" %%a in (data1.txt) do (
  10.   if !num! neq %%a (echo;!num! !未知!)&(set var=)
  11.   if "!var!" neq "%%b" (
  12.     echo;%%a !%%b!
  13.     set var=%%b
  14.   )  
  15.   set /a num=%%a+1
  16. )
  17. )>结果.txt
复制代码





欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2