shell 能实现这样的功能吗?还是要 python?

2016-07-18 20:53:48 +08:00
 fsckzy
求给点思路,
文件是这样的,大概有 5000 多条
1.0.16.0 1.0.31.255
1.0.64.0 1.0.127.255
1.1.64.0 1.1.127.255
1.5.0.0 1.5.255.255
1.21.0.0 1.21.255.255


要用 shell 把它生成这样的
比如说 1.0.16.0 1.0.31.255 ,就要如下的效果
1.0.16.0
1.0.16.1
1.0.16.2
1.0.16.2

。。。
1.0.16.255
1.0.17.0
1.0.17.1
1.0.17.255
1.0.18.0
1.0.18.255
...
1.0.31.0
1.0.31.255
4787 次点击
所在节点    程序员
33 条回复
smilejustforfan
2016-07-19 01:12:04 +08:00
man ipcalc
caola
2016-07-19 01:27:15 +08:00
如果系统自带的东西可以实现,建议尽量不要使用第三方语言或工具,
当然如果效率和占用的资源适合的话,可以考虑自己认为适合的语言来实现
DravenJohnson
2016-07-19 05:20:48 +08:00
实现肯定可以,只是看你想不想这样做,个人感觉还不如写一个 Python 快且容易:





我的 shell 功底比较差,但是总体步骤可以参考。还可以优化但是懒得弄了。
当然还有很多其它办法,楼上说了好几个比如 awk 也可以实现,但是还是那句话,看你想不想这样了因为我觉得 Python 简单。
Owenjia
2016-07-19 09:30:23 +08:00
@msg7086
awk 其实就是一种脚本语言吧…
4everLoveU
2016-07-19 09:44:49 +08:00
可以实现,思路:
先 sort | uniq 排序去重
然后 awk 用" . "切除前三个字符,后面的补一个 for 循环 0~255 ,最后作拼接即可...
araraloren
2016-07-19 10:04:44 +08:00
~~ 对于脚本能解决的问题不存在实现不能实现的问题,只是方便不方便的问题
```perl6
#!/usr/bin/env perl6

sub ip2Int(@ip) {
my Int $ipint = 0;

for ^4 {
$ipint +<= 8; $ipint +|= @ip[$_];
}
$ipint;
}

sub int2Ip($ipint) {
my @ip;

@ip.push: ($ipint +> (8 * .Int)) +& 0xff for ^4;
@ip.reverse;
}

say int2Ip($_) for ip2Int([1, 0, 16, 0]) ... ip2Int([1, 0, 31, 255]);
```
下面是测试 测试,如果你是想要的这种效果的话。。
[TEST LINK]( https://ideone.com/KOG2Gp)
sualwu
2016-07-19 10:52:13 +08:00
debian8:~$ cat iplists
1.1.1.250 1.1.2.10
1.1.2.252 1.1.3.2

debian8:~$ for iplist in `cat iplists | sed -r 's/\s+/##/g'`; do intip1=`echo $iplist | awk -F'##' '{print $1}' | awk -F. '{print($1*2^24+$2*2^16+$3*2^8+$4)}'`; intip2=`echo $iplist | awk -F'##' '{print $2}' | awk -F. '{print($1*2^24+$2*2^16+$3*2^8+$4)}'`; for ((ip=$intip1;ip<=$intip2;ip++)); do ((i1=$ip>>24,i2=$ip>>16&0x00ff,i3=$ip>>8&0x0000ff,i4=$ip&0x000000ff)); echo $i1.$i2.$i3.$i4; done; done
1.1.1.250
1.1.1.251
1.1.1.252
1.1.1.253
1.1.1.254
1.1.1.255
1.1.2.0
1.1.2.1
1.1.2.2
1.1.2.3
1.1.2.4
1.1.2.5
1.1.2.6
1.1.2.7
1.1.2.8
1.1.2.9
1.1.2.10
1.1.2.252
1.1.2.253
1.1.2.254
1.1.2.255
1.1.3.0
1.1.3.1
1.1.3.2
wizardoz
2016-07-19 11:25:29 +08:00
你是在问 bash 有没有循环功能?我告诉你,有!
sunmsn
2016-07-19 16:20:48 +08:00
import netaddr

def ip2int(addr):
return int(netaddr.IPAddress(addr))

def int2ip(addr):
return str(netaddr.IPAddress(addr))

with open('data.txt','r') as f:
for line in f:
ip_1,ip_2 = line.strip().split()
for i in range(ip2int(ip_1),ip2int(ip_2)+1):
print int2ip(i)
print '-'*80
Azus
2016-07-19 18:30:50 +08:00
shell scripts 不就是用来利用和关联各种程序的么, 避免造轮子才是应该的
如果是在 debian 系, 12 楼 @changshu 的答案最好
redhat 系有些不幸,没有 prips, 这个轮子似乎还是可以造一下

@DravenJohnson 23 楼的实现不对, 1.0.16.10 到 1.0.17.0 之间的 ip 缺失

纯 Bash, 没觉得比其它的复杂, 还不依赖其它软件

usage: ./prips.sh iplists_file

----
#!/usr/bin/env bash

ip2int() {
local i
local int

for i in {0..3}; do
((int <<= 8))
((int += $1[i]))
done
echo $int
}

int2ip() {
local i

int=$1

for i in {0..3}; do
((ip[i] = int & 255))
((int >>= 8))
done
echo ${ip[3]}.${ip[2]}.${ip[1]}.${ip[0]}
}

while read -ra ipl; do
s=(${ipl[0]//./ })
e=(${ipl[1]//./ })

for ((i = $(ip2int s); i <= $(ip2int e); i++)) {
int2ip $i
}
done < $1
----
itisthecon
2016-07-19 18:39:38 +08:00
用 perl , 应该是最简洁了吧:

#!/usr/bin/perl
use 5.10.1;
use Socket;
open ( FH,'iplist' );
while ( <FH> ){
my @a = split;
$s = unpack("N", inet_aton ( "$a[0]" ));
$e = unpack("N", inet_aton ( "$a[1]" ));
for ( $i=$s;$i<=$e;$i++ ){
say inet_ntoa(pack("N", $i));
}
}
Balthild
2016-07-20 01:21:13 +08:00
跑个题, php

$arr = explode(" ", $input);
$long1 = ip2long($arr[0]);
$long2 = ip2long($arr[1]);
for ($i = $long1; $i <= $long2; $i++) {
$ips[] = long2ip($i);
}
print_r($ips);
Balthild
2016-07-20 01:27:53 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/293308

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX