

InterviewSolution
1. |
Solve : calculate from values in a text file's first column, ":" delimited, bat, VBs, PS? |
Answer» Please help me program the scenario below: Any Progress? Didn't know we were on the clock. The hard part was retrieving chunks of the file for INDIVIDUAL processing. VBScript was a possible solution as it supports regular expressions, but so does Powershell so I went with the latter. Code: [Select]$file = "c:\myfile.txt" $arrTitles = () $arrEmps = () # Load the Job Titles into Array # (Get-Content -Path $file) -match "^[0-9]{1,3}:[A-Z]{1,}\\[A-Z]{1,}$" | ForEach-Object { $arrTitles += , ( [Convert]::ToDecimal($_.split(":")[0]), $_.split(":")[1] ) } $arrTitles.GetEnumerator() | Sort-Object | Out-Null # Load the Employees into Array # (Get-Content -Path $file) -match "^[0-9]{1,3}:[A-Z]{1,}\s[A-Z]{1,}$" | ForEach-Object { $arrEmps += , ( [Convert]::ToDecimal($_.split(":")[0]), $_.split(":")[1] ) } #Do the LOOKUPS # for($j=0; $j -lt $arrEmps.Count; $j++) { for($i=0; $i -lt $arrTitles.Count - 1; $i++) { if( ($arrEmps[$j][0] -GE $arrTitles[$i][0]) -and ($arrEmps[$j][0] -le $arrTitles[$i+1][0]) ) ` { Write-Host $arrEmps[$j][1], "=", $arrTitles[$i][1] } } } Save the script with a PS1 extension and run from the Powershell command prompt. Powershell does not search the current directory for a script so use the .\ pointer if you need to point to the current directory. The first line of code is the file name. Change as needed. Well done, Sidewinder! Excellent! Thanks you sooo much.I just had to finish it... Save with .vbs extension call with cscript.exe //nologo pass input filename as parameter example cscript //nologo Scriptname.vbs input.txt input.txt... Code: [Select]ServerName: KDB2012\ADUsers --------------------- 2:KALDB\Developers 16:KALDB\ProdDevs 20:KALDB\BADATAREADER 25:KALDB\ZADATAREADER 115:KALDB\AREADER 168:KALDB\PREADER 190:KALDB\PWRITER 192:KALDB\READER 257:KALDB\WRITER 261:KALDB\SWRITER 299:KALDB\ITDataProc 316:KALDB\RDevelopment 340:KALDB\ReadOnly ------------------------- 152:Kalvin Rodger 183:Kalvin Rodger 239:Kalvin Rodger 289:Kalvin Rodger The script... Code: [Select]Const ForReading = 1 Const ForWriting = 2 Set objFSO = CreateObject("Scripting.FileSystemObject") Set ReadFile = objFSO.OpenTextFile (wscript.arguments(0), ForReading) strText = ReadFile.ReadAll Readfile.Close arrFileLines = Split(strText, vbCrLf) i=3 L=0 Dim LimitList() Do sline=arrFileLines(i) ReDim Preserve LimitList (l) LimitList (l) = sline l = l + 1 i = i + 1 Loop until Mid(sline,1,10)="----------" Dim LimitValues() Dim OutPutText() For j = 0 To (UBound(LimitList)-1) MyString=LimitList(j) arrTokens = Split (MyString, ":") ReDim Preserve LimitValues(j) LimitValues(j) = arrtokens(0) ReDim Preserve OutPutText(j) OutPutText(j) = arrTokens(1) Next Dim LookupCode() For j = 0 To (UBound(LimitValues)-1) ReDim Preserve LookupCode(j) LookUpCode (j) = "If (numval > " & LimitValues(j) & ") AND (numval < " & LimitValues(j+1) & ") Then wscript.echo nameval & " & Chr(34) & " = " & OutPutText(j) & Chr(34) Next ReDim Preserve LookupCode(j) LookUpCode (j) = "If (numval > " & LimitValues(UBound(LimitValues)) & ") Then wscript.echo nameval & " & Chr(34) & " = " & OutPutText(j) & Chr(34) For j = i To UBound(arrFileLines) MyString = arrfilelines(j) arrTokens = split(MyString,":") numval=arrTokens(0) Nameval=arrTokens(1) For k = 0 To UBound(LookUpCode) ExecuteGlobal LookUpCode(k) Next Next output... Code: [Select]Kalvin Rodger = KALDB\AREADER Kalvin Rodger = KALDB\PREADER Kalvin Rodger = KALDB\READER Kalvin Rodger = KALDB\SWRITERViola great my friend.In the interest of accuracy, I have since discovered that the Powershell solution has a serious logic flaw and an improper use of the Sort-Object cmdlet. The script worked in spite of the flaws, but will produce inaccurate results under certain circumstances. A newer and better version is posted below: Code: [Select]$file = Join-Path -Path $pwd -ChildPath myfile.txt $arrTitles = () $arrEmps = () # Load the Job Titles into Array # (Get-Content -Path $file) -match "^[0-9]{1,3}:[A-Z]{1,}\\[A-Z]{1,}$" | ForEach-Object { $arrTitles += , ( ( [Convert]::ToDouble($_.split(":")[0]) ).ToString("000"), $_.split(":")[1] ) } $arrTitles = $arrTitles | Sort-Object {Expression={$_[0]}; Ascending=$true} # Load the Employees into Array # (Get-Content -Path $file) -match "^[0-9]{1,3}:[A-Z]{1,}\s[A-Z]{1,}$" | ForEach-Object { $arrEmps += , ( ( [Convert]::ToDouble($_.split(":")[0]) ).ToString("000"), $_.split(":")[1] ) } # Do the Lookups # for($j=0; $j -lt $arrEmps.Count; $j++) { for($i=0; $i -lt $arrTitles.Count - 1; $i++) { if( ($arrEmps[$j][0] -eq $arrTitles[$i+1][0]) ) ` { Write-Host $arrEmps[$j][1], "=", $arrTitles[$i+1][1]; break } if( ($arrEmps[$j][0] -ge $arrTitles[$i][0]) -and ($arrEmps[$j][0] -lt $arrTitles[$i+1][0]) ) ` { Write-Host $arrEmps[$j][1], "=", $arrTitles[$i][1] } } } Sorry for any inconvenience. I've been prettying up my effort too... Code: [Select] Const ForReading = 1 Set objFSO = CreateObject("Scripting.FileSystemObject") ' Read whole input file at once into string Set ReadFile = objFSO.OpenTextFile (wscript.arguments(0), ForReading) strText = ReadFile.ReadAll Readfile.Close ' Split string into individual lines arrFileLines = Split(strText, vbCrLf) Dim LimitList() Dim LimitValues() Dim OutPutText() ' Get first part into array ' Parsed stored file up to second dashed line ' Start at 3rd line InputLine=3 LimitLine=0 ' Read file lines one by one Do sline=arrFileLines(InputLine) ReDim Preserve LimitList (LimitLine) LimitList (LimitLine) = sline LimitLine = LimitLine + 1 InputLine = InputLine + 1 Loop until Mid(sline,1,10)="----------" ' InputLine now points to first line after dashes DataStart = InputLine ' Get band limit values ' Read each line of first block For j = 0 To (UBound(LimitList)-1) ' Split line into 2 tokens at : character arrTokens = Split (LimitList(j), ":") ReDim Preserve LimitValues(j) ' First token is numerical value LimitValues(j) = arrtokens(0) ReDim Preserve OutPutText(j) ' Second token is text string for that band OutPutText(j) = arrTokens(1) Next ' Process second part of input file For j = DataStart To UBound(arrFileLines) ' Split line into 2 tokens at : character arrTokens = split(arrfilelines(j),":") numval=Int(arrTokens(0)) Nameval=arrTokens(1) ' For each line in second part For k = 0 To UBound(Limitvalues) LineToWrite = nameval & " = " & OutPutText(k) ' This is lower test value lower = Int(Limitvalues(k)) ' If not last line check if number is above this band lower limit ' and below next band lower limit If k < UBound(Limitvalues) Then ' This Is next band lower limit upper = Int(Limitvalues(k+1)) ' Do test If (numval > lower) AND (numval < upper) Then wscript.echo LineToWrite End If Else ' If this is last line just test if number is above limit If (numval > lower) Then wscript.echo LineToWrite End If End If Next Next Not sure why am I getting this: RESULTS ARE OK, but in old script C:\Kaldb\adu.vbs(42, 4) Microsoft VBScript runtime error: Subscript out of rang e: '[number: 0]' in new script C:\Kaleem\now.vbs(53, 2) Microsoft VBScript runtime error: Subscript out of rang e: '[number: 0]' 53: numval=Int(arrTokens(0)) 54: numval=arrTokens(1) Quote from: kdb2012 on March 26, 2012, 04:04:41 PM Not sure why am I getting this: Possibly there is a line in input file not as your description; best thing is to learn scripting and then you can write and fix scripts yourself. Does Sidewinder's script GIVES error? |
|