Board logo

标题: [文本处理] 如何获取相同IP段中C段(第三段)的最小值和最大值并按指定格式输出? [打印本页]

作者: uckiss    时间: 2014-8-24 11:01     标题: 如何获取相同IP段中C段(第三段)的最小值和最大值并按指定格式输出?

本帖最后由 pcl_test 于 2016-3-3 21:37 编辑

9.79.12.0
9.79.116.0
9.79.219.0
9.79.221.0
9.79.222.0
149.80.1.0
149.80.42.0
149.80.144.0
149.80.249.0
119.189.73.0
119.189.74.0
119.189.82.0
119.189.84.0
119.189.96.0
119.189.99.0
119.189.84.0
119.189.96.0
119.189.199.0
119.189.255.0

我只会用%%I %%J   %%K转换0或255
求大神写个代码     取C段的最小值和最大值 转换成这种格式
转换成
9.79.12.0-9.79.222.0
149.80.1.0-149.80.249.0
119.189.73.0-119.189.255.0
先谢了
作者: apang    时间: 2014-8-24 12:24

本帖最后由 apang 于 2014-8-24 19:00 编辑
  1. @echo off & setlocal enabledelayedexpansion
  2. for /f "tokens=1-3 delims=." %%a in (a.txt) do (
  3.     if defined Max%%a.%%b (
  4.         if !Max%%a.%%b! lss %%c set "Max%%a.%%b=%%c"
  5.     ) else set "Max%%a.%%b=%%c"
  6.     if defined Min%%a.%%b (
  7.         if !Min%%a.%%b! gtr %%c set "Min%%a.%%b=%%c"
  8.     ) else set "Min%%a.%%b=%%c"
  9. )
  10. (for /f "tokens=1*delims==" %%a in ('"(set Min&set Max)|sort /+4"') do (
  11.     if defined flag (
  12.         if %%b gtr !b! (
  13.             echo,!a:~3!.!b!.0-!a:~3!.%%b.0
  14.         ) else echo,!a:~3!.%%b.0-!a:~3!.!b!.0
  15.         set "flag="
  16.     ) else set "a=%%a" & set /a b=%%b,flag=1
  17. ))>b.txt
  18. pause
复制代码

作者: uckiss    时间: 2014-8-24 15:30

回复 2# apang


    可以用, 谢谢   

就是处理过后,不会保存到文本,

得手动复制到文本才行
手动复制只能复制显示的部分,
帮忙加句代码,,自动保存到指定文本
作者: uckiss    时间: 2014-8-24 16:46

>>  用两个这,就搞定,,,,谢了
作者: 523066680    时间: 2014-8-24 17:01

本帖最后由 523066680 于 2014-8-24 17:23 编辑

也做一个咯
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set /a min=255, max=0
  4. for /f "tokens=1,2,3,4 delims=." %%a in (a.txt) do (
  5. if not "%%a.%%b" == "!ever!" (
  6. if defined ever (
  7. echo !ever!.!min!.0 - !ever!.!max!.0
  8. )
  9. set /a min=255, max=0
  10. )
  11. set ever=%%a.%%b
  12. if %%c gtr !max! (
  13. set /a max = %%c
  14. )
  15. if %%c leq !min! (
  16. set /a min = %%c
  17. )
  18. )
  19. echo !ever!.!min!.0 - !ever!.!max!.0
  20. pause
复制代码
未考虑前面两节地址打乱的情况,for 里面改成 ('sort /r a.txt') 可以解决一般情况。
作者: apang    时间: 2014-8-24 19:05

回复 3# uckiss


    真的可以用吗?
我发现有逻辑错误,以改正
作者: CrLf    时间: 2014-8-24 22:12

本帖最后由 CrLf 于 2014-8-25 00:52 编辑

如果我毫不谦虚地说这是大师级的写法,各位有异议吗...
  1. @echo off&setlocal enabledelayedexpansion
  2. (for /f "tokens=1-3 delims=. " %%a in (a.txt) do (
  3. set /a "(n=%%c)/(max[%%a.%%b]-n>>31),max[%%a.%%b]=n"
  4. set /a "(!min[%%a.%%b]:min[%%a.%%b]=n!)/(n-min[%%a.%%b]>>31),min[%%a.%%b]=n"
  5. )) 2>nul
  6. for /f "delims=max[]" %%a in ('set max[') do (
  7. echo %%a.!min[%%a]!.0-%%a.!max[%%a]!.255
  8. )
  9. pause
复制代码
支持乱序文本,但不对输出排序
作者: 523066680    时间: 2014-8-24 22:58

回复 7# CrLf


    无异议。
作者: apang    时间: 2014-8-25 19:40

回复 7# CrLf


    (!min[%%a.%%b]:min[%%a.%%b]=n!) 猜测这个是条件判断,set /a中使用冒号以前没见过,请教CrLf,到哪里可以找到相关的用法和资料?
作者: CrLf    时间: 2014-8-25 20:13

本帖最后由 CrLf 于 2014-8-25 23:26 编辑

回复 9# apang


玄机不在冒号,而在于变量延迟,可以参考此贴:http://bbs.bathome.net/viewthread.php?tid=15774

以此句为例:
  1. set /a "(!min[%%a.%%b]:min[%%a.%%b]=n!)/(n-min[%%a.%%b]>>31),min[%%a.%%b]=n"
复制代码
分解几个部分来解释一下:

1、(!min[%%a.%%b]:min[%%a.%%b]=n!)
因为变量 min[%%a.%%b] 的值一定为数字,所以脚本中的 !min[%%a.%%b]:min[%%a.%%b]=n! 会有如下变化:
当变量存在时,相当于 !min[%%a.%%b]!
当变量不存在时,相当于 min[%%a.%%b]=n,也就是把 n 赋值给 min[%%a.%%b]

2、(n-min[%%a.%%b]>>31)
>>运算符用于作位偏移计算,假如是 >>1 会将第 32 位的01状态复制到 31 位,丢弃第 1 位,其余位向右偏移
因为负数的第 32 位一定是 1,而正整数的 32 位为 0,所以得出一个规律:负数>>31 = -1,正数>>31 = 0
所以这句的作用是假如 n 小于 min[%%a.%%b] 则得到 1,否则得到 0

3、(!min[%%a.%%b]:min[%%a.%%b]=n!)/(n-min[%%a.%%b]>>31)
分子不重要,如上文说明仅用于在 min[%%a.%%b] 变量不存在时将其定义为 n,将其理解为任意数字皆可
而当分母为 0 时,计算出错,停止 set /a
所以如上文所述,这句相当于当 n 大等于 min[%%a.%%b] 时终止计算

4、min[%%a.%%b]=n
前一个算式执行成功后才会执行这句,将 min[%%a.%%b] 赋值为 n
作者: apang    时间: 2014-8-25 21:02

回复 10# CrLf


    明白了,我还以为!是取反来着,呵呵。谢谢指教。
作者: Linuxer    时间: 2014-8-25 21:28

哈哈。一看就知道必然是高大上的代码,,,留爪以备学习。看着满屏的%感觉很难。。。
作者: CrLf    时间: 2014-8-26 00:29

回复 12# Linuxer


    那些 %%a %%b 是 for 语句的变量,执行 set /a 时它们已经变成数字了...
作者: neorobin    时间: 2014-8-29 11:32

回复 7# CrLf

一样无异议.

JUST I THINK SO

对于max(a,b)和min(a,b), set /a 有这样一些实现:
min
a+(b-a)&(b-a>>31)
(a-b>>31)&a|(b-a>>31)&b
(a-b>>31)&a|~(a-b>>31)&b

max
a-(a-b)&(a-b>>31)
(a-b>>31)&b|(b-a>>31)&a
(a-b>>31)&b|~(a-b>>31)&a

大胆把大师级代码修改玩一下, 未定义的变量被看作 0 , 确实不能忘了, 呃, 我不想用除法!, 假设文档中并无负数. 以下
  1. @echo off & setlocal enabledelayedexpansion
  2. set /a "M=1<<31^-1"
  3. for /f "tokens=1-3 delims=. " %%a in (a.txt) do (
  4.     set /a "x=%%c,t=x-max[%%a.%%b],max[%%a.%%b]=x-(t&t>>31),p=min[%%a.%%b],p=p+(p-1>>31&M),t=p-x,min[%%a.%%b]=x+(t&t>>31)"
  5. )
  6. for /f "delims=max[]" %%a in ('set max[') do (
  7. echo %%a.!min[%%a]!.0-%%a.!max[%%a]!.255
  8. )
  9. pause
复制代码

作者: CrLf    时间: 2014-8-29 15:58

本帖最后由 CrLf 于 2016-3-4 08:38 编辑

回复 14# neorobin


惭愧,玩笑话罢了,随便改
这大概是类似思路下的最优方案了吧?看到兄台代码,本想试试用异运算,大致原理类似这样:
  1. all=a^b
  2. flag=a 大于 b
  3. max=all^a*flag+b*!flag
复制代码
但无法简单判断两数大小,所以还是没法找到更好的方案
作者: codegay    时间: 2016-3-4 04:32

  1. """
  2. IP段整理成a.b.c.0-a.b.c.255的格式.py
  3. http://bbs.bathome.net/thread-31568-1-1.html
  4. 2016年3月3日 02:15:42 codegay
  5. """
  6. import pprint
  7. #生成测试文件
  8. open("3.txt","w+").write("""9.79.12.0
  9. 9.79.116.0
  10. 9.79.219.0
  11. 9.79.221.0
  12. 9.79.222.0
  13. 149.80.1.0
  14. 149.80.42.0
  15. 149.80.144.0
  16. 149.80.249.0
  17. 119.189.73.0
  18. 119.189.74.0
  19. 119.189.82.0
  20. 119.189.84.0
  21. 119.189.96.0
  22. 119.189.99.0
  23. 119.189.84.0
  24. 119.189.96.0
  25. 119.189.199.0
  26. 119.189.255.0""")
  27. txt=open("3.txt").readlines()
  28. abc=[r.split(".")[:-1] for r in txt]
  29. ab=sorted(list({r[0]+'.'+r[1] for r in abc}))
  30. for a in ab:
  31.     ccc=['.'.join(r.split(".")[:-1]) for r in txt if a+"." in r]
  32.     print('整理结果',min(ccc)+'.0'+'-'+max(ccc)+'.255')
  33. """
  34. 输出:
  35. 整理结果 119.189.199.0-119.189.99.255
  36. 整理结果 9.79.116.0-9.79.222.255
  37. 整理结果 149.80.1.0-149.80.42.255
  38. """
复制代码





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