2016-12-23 62 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!

如果你覺得無聊,想給我一個更好的方法,請做。記住...我試圖去學習,因爲我去和我在一個非常基本的水平......所以請去容易解釋:)

亞瑟

相關問題