我有一个纯文本文件,其中包含一些像这样的IP:
194.225.0.0 - 194.225.15.255
194.225.24.0 - 194.225.31.255
62.193.0.0 - 62.193.31.255
195.146.53.128 - 195.146.53.225
217.218.0.0 - 217.219.255.255
195.146.40.0 - 195.146.40.255
85.185.240.128 - 85.185.240.159
78.39.194.0 - 78.39.194.255
78.39.193.192 - 78.39.193.207
我想按IP地址对文件进行排序。我的意思是只有第一部分是重要的。
我在谷歌上找到了一些程序,但我想知道是否有可能通过PowerShell没有其他应用程序。
我有一个像这样的Linux方式,但无法在Windows中达到它:
sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 file
更新1
@TheMadTechnician,这是我运行你的命令时的输出:
85.185.240.128 - 85.185.240.159
195.146.40.0 - 195.146.40.255
78.39.193.192 - 78.39.193.207
78.39.194.0 - 78.39.194.255
217.218.0.0 - 217.219.255.255
194.225.24.0 - 194.225.31.255
194.225.0.0 - 194.225.15.255
195.146.53.128 - 195.146.53.225
62.193.0.0 - 62.193.31.255
8条答案
按热度按时间7fyelxc51#
使用RegEx-replace的简单解决方案:为了使IP地址可排序,我们只需要在左侧填充每个八位字节,以便它们都具有相同的宽度。然后进行一个简单的字符串比较,即可得到正确的结果。
对于PS 6+:
对于PS 5.x:
-replace
操作符尝试在给定字符串中查找 * 正则表达式 * 模式的匹配项,并将其替换为给定的值。-replace
不支持 scriptblock。使用.NETRegex.Replace
方法,我们可以实现相同的功能。$_
表示文本文件的当前行。\d+
是匹配每个IP地址的每个八位字节的模式。有关详细说明,请参见regex101中的示例。{}
定义了一个输出替换值的 scriptblock$_
表示当前匹配(八位字节)。我们取它的值,并在左边填充零,所以每个八位字节总共是3个字符(e。例如,2
变为002
,92
变为092
)。最终的IP可能看起来像194.225.024.000
。使用
Tuple
类的另一种解决方案。它稍长,但更干净,因为它实际上比较数字而不是字符串。[regex]::Matches()
,我们找到当前行的所有数字。从返回的MatchCollection
中,我们获取前四个元素。然后我们使用member access enumeration创建一个字符串数组,其中包含每个MatchCollection
元素的Value
成员。[int[]]
类型约束的变量(int
s的数组),PowerShell会自动将字符串解析为整数。Tuple
实现了IComparable
接口,Sort-Object
在可用时使用该接口。元组按lexicographically排序,正如预期的那样。[Tuple]::Create
调用(最多适用于8个元素1):请注意到
[object[]]
的转换,否则[Tuple]::Create
将只使用一个参数调用,即$octets
数组。[1]实际上,大于8个元素的元组可以通过创建嵌套元组来创建(为剩余的元素创建一个元组,并将其存储在基本元组的最后一个元素中)。一般来说,要做到这一点,需要递归或反向循环,首先创建最嵌套的元组。
yeotifhr2#
这个答案最初是作为我的评论发表在不同的answer
您可以将IP地址从
string
对象转换为version
对象,该对象“巧合地”与IP地址具有相同的格式(由.
分隔的4组数字)mtb9vblg3#
只要第一个二进制八位数中的范围起始地址不同,TheMadTechnician's answer就可以工作。为了让它按多个八位字节排序,
Sort-Object
看起来不会按单个[ScriptBlock]
返回的数组中的连续值排序;为此,您需要为每个八位字节传递[ScriptBlock]
。Santiago Squarzon's answer展示了如何做到这一点,而无需重复定义四个几乎相同的[ScriptBlock]
。相反,一个
[ScriptBlock]
可以将每个八位字节组合成一个[UInt32]
来进行排序。使用
[Math]::Pow()
生成可排序值。输出。。
为了更好的衡量,你可以把第一行改为...
...并查看它是否正确排序,而不会使排序值溢出。
使用
[BitConverter]
生成可排序值您可以通过使用
[BitConverter]
class将IP地址字节直接转换为[UInt32]
...在PowerShell类中实现
[IComparable]
,定义自己的排序一个更复杂的解决方案是将我们的地址存储在一个实现
[IComparable]
interface的类型中,这样Sort-Object
就可以直接对地址进行排序,而不需要指定[ScriptBlock]
。当然,[IPAddress]
是存储IP地址最自然的.NET类型,但它没有实现任何排序接口。相反,我们可以使用PowerShell classes来实现我们自己的可排序类型。[IPAddressRange]
类型存储范围的开始和结束地址,因此它可以表示输入文件的整行。CompareTo
method逐字节比较每个StartAddress
,只有当它们相等时,它才逐字节比较每个EndAddress
。执行这个…...按预期顺序对
127.0.0.*
范围进行排序...请注意,我们只为
Sort-Object
添加了对[IPAddressRange]
示例进行排序的功能,而没有添加其单个属性。这些仍然是[IPAddress]
类型,它不提供自己的顺序,所以如果我们尝试类似... | Sort-Object -Property 'EndAddress'
的东西,它不会产生预期的结果。fdbelqdn4#
一种简单的方法是在
.
上分割每一行,取第一部分(范围内每个IP的第一个八位字节),然后将其转换为整数并进行排序。6ojccjat5#
scottwang提供了一种聪明的方式来排序评论中的IP,使用实现
IComparable
Interface的Version
Class。下面是另一种选择,显然效率较低,使用hash table,
IPAddress
Class和表达式数组:使用advanced function或anonymous function可以在单个管道中执行相同操作:
ttp71kqs6#
我的prior answer效率很低,因此我决定提供另一种替代方案,使用Class实现
IComparable
Interface并持有IpAddress
的示例:现在示例可以Comparable
测试平等
因此,可排序:
6mw9ycah7#
可能是这样的。
sz81bmfz8#
我将使用一个简单的ip地址列表作为示例。[ipaddress]类型的address long integer属性通常是反向字节主机顺序(little endian),因此必须通过HostToNetworkOrder()将其更改为从左到右的网络字节顺序(big endian)。
注意右侧零填充。'255.255.255.255'不适合[int]。