Welcome guest. Before posting on our computer help forum, you must register. Click here it's easy and free.

Author Topic: calculate from values in a text file's first column, ":" delimited, bat, VBs, PS  (Read 12555 times)

0 Members and 1 Guest are viewing this topic.

kdb2012

    Topic Starter


    Rookie

    • Experience: Beginner
    • OS: Unknown
    Yes sidewinder's script throws errors, but I am concentrating more on VB as I have some prior experience. But as I mentioned in my first post that the files I receive are dynamic and the contents changes every time. But the overall pattern remains the same.
    1: server name (may or may not have \instance)
    2: -----------------------------
    3:domain\AD_Group
    ...
    n:domain\AD_Group
    (n+1):--------------------------
    (n+2):AD_User that belongs to AD_Group(s) above
    ...
    m:AD_User that belongs to AD_Group(s) above


    That's it.
    Thanks!

    Salmon Trout

    • Guest
    The example text file you provided does not throw any errors with the script I posted, so something must be different. I wonder if there are extra blank lines at the end of the files that cause the error? Could you post an example of a file that gave the error messages?

    Sidewinder



      Guru

      Thanked: 139
    • Experience: Familiar
    • OS: Windows 10
    Quote
    Yes sidewinder's script throws errors, but I am concentrating more on VB as I have some prior experience.

    I too would be interested to know what those errors are. I can't get it to fail with your original test file, or my souped up test file or even a test file with embedded blank records.

    Posting an example of a test file that produced any errors would be most helpful.

     8)

    The true sign of intelligence is not knowledge but imagination.

    -- Albert Einstein

    Salmon Trout

    • Guest
    See the CR/LF?



    Code: [Select]
    C:\Batch\Test>Readfile-CH.vbs Input2.txt
    Kalvin Rodger = KALDB\AREADER
    Kalvin Rodger = KALDB\PREADER
    Kalvin Rodger = KALDB\READER
    Kalvin Rodger = KALDB\SWRITER
    C:\Batch\Test\Readfile-CH.vbs(51, 4) Microsoft VBScript runtime error: Subscript out of range: '[number: 0]'


    Sidewinder



      Guru

      Thanked: 139
    • Experience: Familiar
    • OS: Windows 10
    Quote
    See the CR/LF?

    Indeed I do. However the regular expression filtered out any records that did not match the pattern. Powershell was used to have access to a sort technique in case the AD_Group was not sequenced. I still can't get the Powershell version to fail even with the hanging CR/LF.

    I know the OP prefers the VBS, just looking for why the PS version throws errors.

     8)
    The true sign of intelligence is not knowledge but imagination.

    -- Albert Einstein

    kdb2012

      Topic Starter


      Rookie

      • Experience: Beginner
      • OS: Unknown
      This is the files I worked on today:

      ServerName: KADB
      ------------------------------------
      2:KALDB\AD Development
      15:KALDB\DB-BDATAREADER)
      20:KALDB\ETL_USERS
      24:KALDB\API2
      30:KALDB\prod_development
      ------------------------------------

      Note: In this the user is not found (this line is not part of the file)

      Yesterday it was this file
      ServerName: KADB
      ------------------------------------
      2:KALDB\AD QA
      15:KALDB\BIREADER)
      20:KALDB\ETL_USERS
      24:KALDB\BIWriter
      30:KALDB\dbowners
      ------------------------------------
      3:Sue Ling
      25:Sue Ling
      31:Sue Heimer

      kdb2012

        Topic Starter


        Rookie

        • Experience: Beginner
        • OS: Unknown
        With Sidewinder's script nothing is returned for this file:

        ServerName: KADB
        ------------------------------------
        2:KALDB\AD Development
        15:KALDB\DB-BDATAREADER)
        20:KALDB\ETL_USERS
        24:KALDB\API2
        30:KALDB\prod_development
        ------------------------------------
        3:Sue Ling
        25:Sue Ling
        31:Sue Hemmer


        oldun

        • Guest
        Try this:
        Code: [Select]
        Option Explicit
        Dim file, domain(), users(), i, j, temp, tmparr
        If WScript.Arguments.Count=0 Then
        WScript.Echo "Required filename not specified....Quitting"
        wscript.quit()
        End If
        file=WScript.Arguments(0)
        UpdateArrays file, domain, users
        on error resume next
        i=ubound(users)
        if err.number then
        wscript.Echo "No users...Quitting"
        wscript.quit
        end if
        i=ubound(domain)
        if err.number then
        wscript.Echo "No domain...Quitting"
        wscript.quit
        end if
        on error goto 0
        for i=ubound(domain)-1 to 0 Step -1
        for j=0 To i
        if domain(j)>domain(j+1) then
        temp=domain(j+1)
        domain(j+1)=domain(j)
        domain(j)=temp
        end if
        next
        next

        for i=0 To ubound(users)
        for j=1 To ubound(domain)
        if (domain(j)>users(i)) Then
        tmparr=Split(Users(i),":")
        temp=tmparr(1) & " = "
        tmparr=split(domain(j-1),":")
        temp=temp & tmparr(1)
        wscript.echo temp
        exit for
        elseif users(i)>domain(ubound(domain)) then
        tmparr=Split(Users(i),":")
        temp=tmparr(1) & " = "
        tmparr=split(domain(ubound(domain)),":")
        temp=temp & tmparr(1)
        wscript.echo temp
        exit for
        end if
        next
        next

        Sub UpdateArrays(file,ByRef ar1,ByRef ar2)
        Const ForReading=1
        Dim fso,infile,i1,i2,line
        Dim regex1,regex2,match,matches1,matches2
        Set regex1=New RegExp
        Set regex2=New RegExp
        regex1.Pattern="^\d+:\w+\\\w+$"
        regex2.Pattern="^\d+:\w+\s\w+$"
        regex1.Global=True
        regex2.Global=True
        Set fso=CreateObject("Scripting.FileSystemObject")
        if (Not fso.FileExists(file)) Then
        WScript.Echo file & " does not exist...Quitting"
        WScript.Quit()
        End If
        Set inFile=fso.OpenTextFile(file,ForReading)
        i1=0
        i2=0
        Do While Not infile.AtEndOfStream
        line=infile.ReadLine
        Set matches1=regex1.Execute(line)
        Set matches2=regex2.Execute(line)
        for each match in matches1
        redim preserve ar1(i1)
        line=Split(line,":")
        ar1(i1)=Right(String(4,"0") & line(0),4) & ":" & line(1)
        i1=i1+1
        next
        for each match in matches2
        redim preserve ar2(i2)
        line=Split(line,":")
        ar2(i2)=Right(String(4,"0") & line(0),4) & ":" & line(1)
        i2=i2+1
        next
        loop
        infile.close()
        End Sub

        Sidewinder



          Guru

          Thanked: 139
        • Experience: Familiar
        • OS: Windows 10
        I dislike unfinished business. Regular Expressions (RegEx) are difficult to read, difficult to write and difficult to maintain. When the data pattern changes, as it did in the second sample, the RegEx must change also. So with a little help from a RegEx tool, a tweak here and there and much headbanging, Version 3.0 has arrived:

        Code: [Select]
        #Requires -Version 2.0

        $file = Join-Path -Path $pwd -ChildPath myFile.txt
        $arrGroups = @()
        $arrUsers = @()

        # Load the Groups into Array
        #
        (Get-Content -Path $file) -match "^[0-9]{1,3}:[A-Za-z0-9]{1,}\\(\s|\S){1,}$" |
          ForEach-Object {
            $arrGroups += , @( [int] $_.split(":")[0], $_.split(":")[1] )
          }
         
        $arrGroups = $arrGroups | Sort-Object @{Expression={$_[0]}; Ascending=$true}

        # Load the Users into Array
        #
        (Get-Content -Path $file) -match "^[0-9]{1,3}:[A-Z]{1,}\s[A-Z]{1,}$" |
          ForEach-Object {
            $arrUsers += , @( [int] $_.split(":")[0], $_.split(":")[1] )
          }
           
        # Do the Lookups
        #
        for($j=0; $j -lt $arrUsers.Count; $j++) {
          for($i=0; $i -lt $arrGroups.Count - 1; $i++) {

            if( ($arrUsers[$j][0] -eq $arrGroups[$i+1][0]) ) `
              { Write-Host $arrUsers[$j][1], "=", $arrGroups[$i+1][1]; break }

            if( ($arrUsers[$j][0] -gt $arrGroups[$i][0]) -and ($arrUsers[$j][0] -lt $arrGroups[$i+1][0]) ) `
                { Write-Host $arrUsers[$j][1], "=", $arrGroups[$i][1]; break }
               
            if( ($arrUsers[$j][0] -ge $arrGroups[$arrGroups.Count - 1][0]) ) `
              { Write-Host $arrUsers[$j][1], "=", $arrGroups[$arrGroups.Count-1][1]; break }
               
          }
        }

        The $file variable holds the name of the input file. The default is to have both the script and the file in the current directory, so you can run the script as: .\scriptname.ps1
        This can be changed by the user.

        If the input data pattern changes again, you have an opportunity to make the changes. Good luck  :D
        The true sign of intelligence is not knowledge but imagination.

        -- Albert Einstein

        kdb2012

          Topic Starter


          Rookie

          • Experience: Beginner
          • OS: Unknown
          @Oldun,
          remarkably fast and accurate.

          Thank you a lot.

          @SideWinder
          this is perfect version, cheers!

          All of you deserve Kudos  ;)