2016-12-23 58 views
2

我的数据是这样的:VBScript - 如何通过数值对文本文件中的字母数字字符串进行排序?

9999.81GB increase - "c:\$RECYCLE.BIN" 1.91GB total 
11.54GB increase - "c:\Program Files (x86)" 11.55GB total 
101.57GB increase - "c:\Windows" 101.61GB total 

我希望它看起来像这样:

9999.81GB increase - "c:\$RECYCLE.BIN" 1.91GB total 
101.57GB increase - "c:\Windows" 101.61GB total 
11.54GB increase - "c:\Program Files (x86)" 11.55GB total 

我一直在试图冒泡排序此。我假设我需要首先在第一个“。”之前将字符串分开。这将是一个可用于排序的数字。我已经用类似这样的方法来解决这个问题:

Const ForReading = 1 
Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objFile1 = objFSO.OpenTextFile("C:\Source.txt", ForReading) 

Do Until objFile1.AtEndOfStream 
FileContent = objFile1.ReadLine 
arr1 = Split(FileContent,".",2) 
arr2 = Array(arr1(0)) 

For i=0 to UBound(arr2) 
WScript.Echo arr2(i) 

Next 
Loop 

但是,我不需要回显,而是需要在气泡排序中使用这些值。这是我似乎被卡住的地方。

我打算使用不同类型的排序..但永远不会有很多行来排序,所以我想泡沫可能是一个不错的选择。

这里是我已经能够做到最好:

Const ForReading = 1 
Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objOpen = objFSO.OpenTextFile("C:\Source.txt", ForReading) 

Do Until objOpen.AtEndOfStream 
FileContent = objOpen.ReadLine 
arr1 = Split(FileContent,".",2) 
arr2 = Array(arr1(0)) 

Do 
x = UBound(arr2) 
    y = -1 
    For j = LBound(arr2) to x - 1 
     If arr(j) > arr2(j + 1) Then 
     TempValue = arr2(j + 1) 
     arr2(j + 1) = arr2(j) 
     arr2(j) = TempValue 
     y = j 
     End If 
    Next 
    x = y 
Loop Until y = -1 

z = "" 
For i = UBound(arr2) To LBound(arr2) 
    z = z & arr2(i) & "." & arr1(1) & vbCrlf 

Next 
Loop 
WScript.echo z 

但这只是输出的最后一行,并没有出现有甚至试图进行排序。

我是新来的:)任何帮助将不胜感激。

亚瑟

+0

单位是否总是用GB表示? – Tomalak

+0

它们最初在KB中没有标记为KB。通过以前的流程,我将它们转换为GB并添加了“GB”以便于阅读。 但是,您的问题的答案是,在“source.txt”中,因为它现在存在,它始终是GB。 – ApexArthur

+0

请注意,使用的数字可能没有意义(增加与总数) - 我手动输入它们用于测试目的。 – ApexArthur

回答

0

我读了几次,并且它在我看来,问题是“为什么它不排序?”

“但是,这只输出最后一行,它似乎甚至没有尝试排序。”

答案很简单:您试图仅对一行数据进行排序。这里是你的算法的伪代码的轮廓:

Read line by line (outer loop) 
    extract the number and place it into arr2 
    bubble sort algorithm on top of arr2 that contains data for 1 line only(inner loop) 
end outer loop 

我得到了我的窗户框所以这里是VBScript.The最复杂的部分工作版本的getSize()函数,因为它需要做的仔细解析提取大小的字符串。我投入了大小单位转换以及支持GB,MB和KB。

' -----------------------------------------------------------' 
' the most complicated part: extracts size info form the string 
Function getSize (line) 
    kbSize = 0 

    ' check that there is a data in the line 
    if Len(line) <> 0 then 
     arr = Split(line," ") 
     ' extract the size and the unit of measurement 
     size = Left(arr(0), Len(arr(0))-2) 
     unit = UCase(Right(arr(0), 2)) 
     ' convert all sizes to KBs 
     select case unit 
      case "GB" 
       kbSize = size * 1024 * 1024 
      case "MB" 
       kbSize = size * 1024 
      case "KB" 
       kbSize = size 
      case else 
       Err.raise 101, "getSize", "do not recignize the size unit " + unit + " in the line " + line 
     end select 
    end if 

    ' remember that the size is not integer 
    getSize = CDbl(kbSize) 
End Function 

' -----------------------------------------------------------' 
' your main program flow 

Const ForReading = 1 
Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objFile1 = objFSO.OpenTextFile("Source.txt", ForReading) 

' slurp the whole file into memory 
content = objFile1.ReadAll 
'split file into arry line by line 
lines = Split(content, vbCrLf) 

' bubble sort lines to avoid brain strain 
For i = LBound(lines) to UBound(lines) 
    For j = i+1 to UBound(lines) 
     If getSize(lines(i)) < getSize(lines(j)) Then 
     TempValue = lines(i) 
     lines(i) = lines(j) 
     lines(j) = TempValue 
     End If 
    Next 
Next 

' get the sorted array and join it back into string for easy of output 
output = Join(lines, vbCrLf) 
WScript.echo output 
+0

这完美的作品!谢谢:) – ApexArthur

+0

我删除了KB转换和case case,因为我将始终有GB值一起工作。 以前,我总是有问题将.ReadAll中的分割线输入到排序中。您的功能方法解决了这个问题 – ApexArthur

+0

很高兴为您效劳。我们倾向于忘记整个编程动物园一开始可能会有多混乱。但时间越来越简单:) 我也想发表评论,面条的解决方案是完全正确的,并可以在更复杂的情况下更好。对于这个特定的情况,恕我直言,这只是一点点。 –

0

这将使用记录,他们可以在内存中创建,然后排序和筛选。它使用正则表达式来查找可能是数字还是日期。 RegEx假定英文数字和日期,如果不是这样,则更改。

它是更大程序的一部分,因此param1在此处被忽略。

它使用重定向而不是打开和关闭文件。出于这个原因,它必须与CSCript一起运行。

Set Arg = WScript.Arguments 
set WshShell = createObject("Wscript.Shell") 
Set Inp = WScript.Stdin 
Set Outp = Wscript.Stdout 

    Set rs = CreateObject("ADODB.Recordset") 
    If LCase(Arg(1)) = "n" then 
    With rs 
     .Fields.Append "SortKey", 4 
     .Fields.Append "Txt", 201, 5000 
     .Open 
     Do Until Inp.AtEndOfStream 
      Lne = Inp.readline 
      SortKey = Mid(Lne, LCase(Arg(3)), LCase(Arg(4)) - LCase(Arg(3))) 
      If IsNumeric(Sortkey) = False then 
       Set RE = new Regexp 
       re.Pattern = "[^0-9\.,]" 
       re.global = true 
       re.ignorecase = true 
       Sortkey = re.replace(Sortkey, "") 
      End If 
      If IsNumeric(Sortkey) = False then 
       Sortkey = 0 
      ElseIf Sortkey = "" then 
       Sortkey = 0 
      ElseIf IsNull(Sortkey) = true then 
       Sortkey = 0 
      End If 
      .AddNew 
      .Fields("SortKey").value = CSng(SortKey) 
      .Fields("Txt").value = Lne 
      .UpDate 
     Loop 
     If LCase(Arg(2)) = "a" then SortColumn = "SortKey ASC" 
     If LCase(Arg(2)) = "d" then SortColumn = "SortKey DESC" 
     .Sort = SortColumn 
     Do While not .EOF 
      Outp.writeline .Fields("Txt").Value 
      .MoveNext 
     Loop 
    End With 

    ElseIf LCase(Arg(1)) = "d" then 
    With rs 
     .Fields.Append "SortKey", 4 
     .Fields.Append "Txt", 201, 5000 
     .Open 
     Do Until Inp.AtEndOfStream 
      Lne = Inp.readline 
      SortKey = Mid(Lne, LCase(Arg(3)), LCase(Arg(4)) - LCase(Arg(3))) 
      If IsDate(Sortkey) = False then 
       Set RE = new Regexp 
       re.Pattern = "[^0-9\\\-:]" 
       re.global = true 
       re.ignorecase = true 
       Sortkey = re.replace(Sortkey, "") 
      End If 
      If IsDate(Sortkey) = False then 
       Sortkey = 0 
      ElseIf Sortkey = "" then 
       Sortkey = 0 
      ElseIf IsNull(Sortkey) = true then 
       Sortkey = 0 
      End If 
      .AddNew 
      .Fields("SortKey").value = CDate(SortKey) 
      .Fields("Txt").value = Lne 
      .UpDate 
     Loop 
     If LCase(Arg(2)) = "a" then SortColumn = "SortKey ASC" 
     If LCase(Arg(2)) = "d" then SortColumn = "SortKey DESC" 
     .Sort = SortColumn 
     Do While not .EOF 
      Outp.writeline .Fields("Txt").Value 
      .MoveNext 
     Loop 
    End With 


    ElseIf LCase(Arg(1)) = "t" then 
    With rs 
     .Fields.Append "SortKey", 201, 260 
     .Fields.Append "Txt", 201, 5000 
     .Open 
     Do Until Inp.AtEndOfStream 
      Lne = Inp.readline 
      SortKey = Mid(Lne, LCase(Arg(3)), LCase(Arg(4)) - LCase(Arg(3))) 
      .AddNew 
      .Fields("SortKey").value = SortKey 
      .Fields("Txt").value = Lne 
      .UpDate 
     Loop 
     If LCase(Arg(2)) = "a" then SortColumn = "SortKey ASC" 
     If LCase(Arg(2)) = "d" then SortColumn = "SortKey DESC" 
     .Sort = SortColumn 
     Do While not .EOF 
      Outp.writeline .Fields("Txt").Value 
      .MoveNext 
     Loop 
    End With 
    ElseIf LCase(Arg(1)) = "tt" then 
    With rs 
     .Fields.Append "SortKey", 201, 260 
     .Fields.Append "Txt", 201, 5000 
     .Open 
     Do Until Inp.AtEndOfStream 
      Lne = Inp.readline 
      SortKey = Trim(Mid(Lne, LCase(Arg(3)), LCase(Arg(4)) - LCase(Arg(3)))) 
      .AddNew 
      .Fields("SortKey").value = SortKey 
      .Fields("Txt").value = Lne 
      .UpDate 
     Loop 
     If LCase(Arg(2)) = "a" then SortColumn = "SortKey ASC" 
     If LCase(Arg(2)) = "d" then SortColumn = "SortKey DESC" 
     .Sort = SortColumn 
     Do While not .EOF 
      Outp.writeline .Fields("Txt").Value 
      .MoveNext 
     Loop 
    End With 
    End If 

排序

filter Sort {n|d|t|tt} {a|d} startcolumn endcolumn 

排序文件

n - extracts a number from the columns specified. Looks for the first number. 
d - extracts a time or date from the columns specified. Looks for the first date. 
t - extracts a text string including spaces from the columns specified. 
tt - extracts a text string discarding leading and trailing spaces from the columns specified. 

a - sorts acending 
d - sorts decending 

startcolumn - the starting column, the first character is column 1 

endcolumn - the ending column 

cscript //nologo filter.vbs sort n a 1 11 < "%windir%\win.ini" 

请参阅filter.zip https://1drv.ms/f/s!AvqkaKIXzvDieQFjUcKneSZhDjw,其中充满了VBS文本处理例程。

  • 筛选文件通过正规表示

  • 查找和替换使用正expresions一个文件中的文本。在命令行上还提取从文件

  • 过滤字符串,然后选择一个和下一个行

使用VBScript表达式

  • 运行VBScript的文本中指定针对每一行

Sorting

  • 排序文件数字,字母顺序,或按日期

  • 随机化线在一个文件中取消排序

  • 删除文件中的重复行

  • 反转文本用于反向搜索的行

  • 交换行i的顺序呐文件

空行和空格从顶部

  • 修剪空白行或文件的底部

  • 修剪引导和拖尾空格

  • 删除所有空行从文件

  • 修复行尾

一般

  • 讲文本朗读

  • 将HTML转换成文本

  • 移除或离开从顶部指定的行数或文件底部

  • 写入标准输入到文件和stdout

  • 计数在一个文件中的行,并设置一个环境变量与统计

剪贴板和Web服务器

过滤器还可以作为一个来源写给StdOut。

  • 写入剪贴板中的内容到stdout

  • 写入指定的网页内容到stdout

+0

Thanks Noodles谢谢你的面条,这对我来说很难,因为我是一个初学者,我会仔细研究并试着去了解它 – ApexArthur

+0

记住代码是重复的,只允许复制和粘贴部分你需要。有4个独立的部分 - 数字,日期,文字,并修剪每个部分站在它自己的文本。所以只需要数字部分。并删除日期和文本部分。 –

+0

http://download.microsoft.com/download/winscript56/Install/5.6/W982KMeXP/EN-US/scrdoc56en.exe –

1

我能找到使用托默勒格领先的零想法的解决方案。我无法使用.ReadAll工作。这是我做的:

Const ForReading = 1 
Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objFile1 = objFSO.OpenTextFile("C:\Source.txt", ForReading) 
Set objFile2 = objFSO.CreateTextFile("C:\Result.txt") 
Do Until objFile1.AtEndOfStream 
Line = objFile1.ReadLine 
Split1 = Split(Line,".",2) 
Split2 = Split1(0) 

result = string(7 - Len(Split2), "0") & Line 
objFile2.Write result & vbCrlf 

Loop 

从这里我只是用Windows命令提示符排序它。

我知道这可能不理想..但它的工作原理!感谢Tomalak!

如果你觉得无聊,想给我一个更好的方法,请做。记住...我试图去学习,因为我去和我在一个非常基本的水平......所以请去容易解释:)

亚瑟

相关问题