ForEach-Object loop get back to 1 line

Hello,

As the $foreach.movenext(), i need to go to the precedent line, but how ?

As you can see :

########################################################
#         Calcul du nombre d'images Orphelines         #
#                Fait le 29/10/2020                    #
#                    NetBackup                         #
########################################################

##Traitement fichier NB_bpmedia.lst
$NB_bpmedia = Get-content "C:\Lab\Pogather-3.02_Win_64\NB_bpmedia.lst"
$DP_MSDP = Get-Content "C:\Lab\Pogather-3.02_Win_64\DP_MSDP_images_masterserverrie_2.lst"
$ImageCatalog = "C:\Lab\ImageCatalog.txt"
$ImageMSDP = "C:\Lab\ImageMSDP.txt"
$ImagesUniqueMSDP = "C:\Lab\ImagesUniqueMSDP.txt"

If(Test-Path -path $ImageCatalog ){Remove-Item $ImageCatalog}
If(Test-Path -path $ImageMSDP ){Remove-Item $ImageMSDP}
If(Test-Path -path $ImagesUniqueMSDP ){Remove-Item $ImagesUniqueMSDP}


#Filtrer par media-ID
#Explorer chaque media-ID de chaque Backup-ID Et Recuperer numero de Copy 
#SI Media-IF que je cherche refaire backup-ID_numeroBID_Cnumerocopy >> go fichier
$LigneFile = $NB_bpmedia.LongLength
$i = 0

ForEach($Rec in $NB_bpmedia){
    If($Rec -like "*IMAGE*"){
        $BID = ($Rec | FindStr /i "IMAGE").Split(" ")[3]
        Write-Host "Backup-ID: $BID" -ForegroundColor Green
        Do{
            $null = $ForEach.MoveNext()
            $NextLine = $ForEach.Current
            $CopyNbr = $Nextline.Split(" ")[1]
            $MediaID = $NextLine.Split(" ")[8] 
            Write-Host "Media-ID: $Media-ID" -ForegroundColor Red
            Write-Host "Ligne Suivante : $NextLine" -ForegroundColor Cyan
            If($MediaID -like "*@aaaaz*"){
                $Image = $BID+"_C"+$CopyNbr
                $Image | Out-File -FilePath $ImageCatalog -Append
                Write-Host "Boucle IF N°2"
            } 
        }  
        Until($NextLine -like "*IMAGE*")
Need to go to the precedent line here !
    }
}

Thx for reply.

Can you tell us what are you trying to achieve ?, it will help folks here to understand the code better.

Hello Kv,

It’s a little bit tricky too explain, and i don’t have the file to show you, but i can try to create the file :

IMAGE server.powershell.org server.powershell.org_12345678
FRAG 1 1 0 0 0 0 @aaaab
FRAG 2 1 0 0 0 0 @aaaac
FRAG 1 2 0 0 0 0 @aaaab
IMAGE server2.powershell.org server2.powershell.org_12345678
FRAG 1 1 0 0 0 0 @aaaac
FRAG 1 2 0 0 0 0 @aaaab
FRAG 1 3 0 0 0 0 @aaaab

In this file i need to seach, each line with the word “IMAGE”:
After this line i must to go to next line and search if i have the Media-ID like “@aaaac”.
If i have i must take a part from the first line “server.powershell.org_12345678_C2”, add the text “_C”+2 of the third line what is the number of the copy.
and put the result in a file.
i done the same thing for each line until the new line IMAGE, where i must donne exactly the same thing.

But the problm in my code is my test Until, to done the test i’m already athe the second line IMAGE, so when i come back to the If, i don’t read it !
It’s why i need to know if it’s possible to come back to the precedent line like the $foreach.movenext(), why not $foreach.moveprevious()

I hope my explication are clear for you :wink:

Thx .

The attempted parsing looks very VBScript. Here is an example showing you how to parse each line as you have a somewhat simple pattern:

$file = @"
IMAGE server.powershell.org server.powershell.org_12345678
FRAG 1 1 0 0 0 0 @aaaab
FRAG 2 1 0 0 0 0 @aaaac
FRAG 1 2 0 0 0 0 @aaaab
IMAGE server2.powershell.org server2.powershell.org_12345678
FRAG 1 1 0 0 0 0 @aaaac
FRAG 1 2 0 0 0 0 @aaaab
FRAG 1 3 0 0 0 0 @aaaab
"@ -split [environment]::NewLine

$results = foreach ($row in $file) {
    if ($row -like 'IMAGE*') {
        Write-Host ('Starting new record for: {0}' -f $row)
        $rowNumber = 1
        if ($props) {
            New-Object -TypeName PSObject -Property $props
            $props.Clear()
        }

        $props = @{
            Server   = ($row -split ' ')[1]
            ServerId = ($row -split ' ')[2]
        }
        $rowNumber++
    }
    else {
        Write-Host ('Parsing row number {0}: {1}' -f $rowNumber, $row)

        switch ($rowNumber) {
            2 {$props.Add('FirstRowUnderImage',($row -split ' ')[1])}
            3 {$props.Add('SecondRowUnderImage',($row -split ' ')[2])}
            4 {$props.Add('ThirdRowUnderImage',($row -split ' ')[-1])}
        }
        $rowNumber++
    }
}

$results

This walks you through the parsing a bit:

Starting new record for: IMAGE server.powershell.org server.powershell.org_12345678
Parsing row number 2: FRAG 1 1 0 0 0 0 @aaaab
Parsing row number 3: FRAG 2 1 0 0 0 0 @aaaac
Parsing row number 4: FRAG 1 2 0 0 0 0 @aaaab
Starting new record for: IMAGE server2.powershell.org server2.powershell.org_12345678
Parsing row number 2: FRAG 1 1 0 0 0 0 @aaaac
Parsing row number 3: FRAG 1 2 0 0 0 0 @aaaab
Parsing row number 4: FRAG 1 3 0 0 0 0 @aaaab

This would produce the following from the file:

ServerId            : server2.powershell.org_12345678
FirstRowUnderImage  : 1
SecondRowUnderImage : 2
Server              : server2.powershell.org
ThirdRowUnderImage  : @aaaab

ServerId            : server.powershell.org_12345678
FirstRowUnderImage  : 1
SecondRowUnderImage : 1
Server              : server.powershell.org
ThirdRowUnderImage  : @aaaab

Renaud,

You had me until “If I have I must take a part from the first line “server.powershell.org_12345678_C2”, add the text “_C”+2 of the third line what is the number of the copy and put the result in a file.” Maybe if you gave an example of using this input, this should be the output would help. Regardless, I don’t think there is any easy way to “moveprevious()”, but I have another idea to do what you want that might be a little simplar.

$text=Get-Content -Raw .\search.txt
ForEach ($group in $text -split "IMAGE ") {
    if ($group | Select-String -Quiet -Pattern "@aaaac") {
        #do stuff
        $group
    }
}

In this example, I read the entire contents of your file as a single string instead of an array of strings by using the -raw switch. Using your example just get rid of the original split on new line. By doing this, I can use the split operator to make an array for each group that starts with “IMAGE”. From there you can use Select-String or any other way you want to look for your criteria.

Hello Rob & Mike ^^,

 

Just information it’s just an little exemple of the file format i have, Really it’s a file with more 10 000 line.

So i think the Rob way could not be used, perhap’s i’m wrong.

 

@Mike :

What i want to do when i have found a line with the mediaID : @aaaac

I just explain more what the file contain :

IMAGE server.powershell.org server.powershell.org_12345678
FRAG 1 1 0 0 0 0 @aaaab
FRAG 2 1 0 0 0 0 @aaaac
FRAG 1 2 0 0 0 0 @aaaab
IMAGE server2.powershell.org server2.powershell.org_12345678
FRAG 1 1 0 0 0 0 @aaaac
FRAG 1 2 0 0 0 0 @aaaab
FRAG 1 3 0 0 0 0 @aaaab
It's a part of a log create by an other script from Veritas NetBackup, so a Backup solution.
IMAGE and FRAG is the Type :
IMAGE is the Backup
FRAG is fragment of the Backup behind.
Ligne IMAGE :
- Column 1 : IMAGE
- Column 2 : Name of the server backup
- Column 3 : Backup-ID of the backup
Ligne FRAG :
- Column 2 : 1 is the number of copy, can be 1 / 2 / 3 ..., but there is in my cas almost Copy 1 or 2
- Column 3 : 1 / 2 / 3 ... number of the Fragment
- Column 4 / 5 / 6 / 7 : i don't know
Raw 8 : Is the Media-ID so the ID of the storage where the backup is hosted.
We have 4 storages different, so 4 Media-ID, but i'm looking for one example the @aaaac.
So Now, when i have found the line IMAGE, i keep the Backup-ID in variable
Search below the Media-ID @aaac until to the next line IMAGE.
If i found @aaaac :
- Take the number of Copy = $CopyNumber
- Concat Backup-ID+"_C"+$CopyNumber and put it in a file with the Out-File.
Exemple of a real File but just the 2 firt Backup, here the test for was searching the @aaaaz:
IMAGE MasterServerRIE.powershell.org 13 MasterServerRIE.powershell.org_1603357143 Orph-Policy-Lab 13 Sched-Lab 0 0 5007 1603961943 0 0 0
FRAG 1 1 20224 0 0 0 0 @aaaaz masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;
FRAG 1 2 20224 0 0 0 0 @aaaaz masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;
FRAG 2 1 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 2 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 3 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 4 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 5 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 6 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 7 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 8 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 9 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 10 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 11 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
FRAG 2 12 6995 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961943 0 0 6 *NULL* 0
IMAGE MasterServerRIE.powershell.org 13 MasterServerRIE.powershell.org_1603357036 Orph-Policy-Lab 13 Sched-Lab 0 0 5007 1603961836 0 0 0
FRAG 1 1 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 2 1 20224 0 0 0 0 @aaaaz masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 2 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 3 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 4 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 5 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 6 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 7 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 8 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 9 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 10 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 11 20224 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0 1603961836 0 0 6 *NULL* 0
FRAG 1 12 6995 0 0 0 0 @aaaab masterserverrie.powershell.org 262144 0 0 -1 4 1;PureDisk;masterserverrie.powershell.org;dp_MasterServer_Lab_RIE;PureDiskVolume;0

Hello all,

 

Ok i’v found out ^^ :

 

########################################################
#         Calcul du nombre d'images Orphelines         #
#                Fait le 29/10/2020                    #
#                    NetBackup                         #
########################################################
##Traitement fichier NB_bpmedia.lst
$NB_bpmedia = Get-content "C:\Lab\Pogather-3.02_Win_64\NB_bpmedia.lst"
$DP_MSDP = Get-Content "C:\Lab\Pogather-3.02_Win_64\DP_MSDP_images_masterserverrie_2.lst"
$ImageCatalog = "C:\Lab\ImageCatalog.txt"
$ImageMSDP = "C:\Lab\ImageMSDP.txt"
$ImagesUniqueMSDP = "C:\Lab\ImagesUniqueMSDP.txt"

If(Test-Path -path $ImageCatalog ){Remove-Item $ImageCatalog}
If(Test-Path -path $ImageMSDP ){Remove-Item $ImageMSDP}
If(Test-Path -path $ImagesUniqueMSDP ){Remove-Item $ImagesUniqueMSDP}


#Filtrer par media-ID
#Explorer chaque media-ID de chaque Backup-ID Et Recuperer numero de Copy 
#SI Media-IF que je cherche refaire backup-ID_numeroBID_Cnumerocopy >> go fichier
$NbrLigne = $NB_bpmedia.LongLength
$i = 0

ForEach($Line in $NB_bpmedia){
    $Line = $NB_bpmedia[$i]
    Write-Host "$Line"
    If($Line -like "*IMAGE*"){
        $BID = $Line.Split(" ")[3]
        Write-Host "$BID" -ForegroundColor Green
    }
    Do{
        $i++
        $x = $NB_bpmedia[$i]
        Write-Host "$i" -ForegroundColor Red
        Write-Host "$x" -ForegroundColor Yellow
        $CopyNumber = $NB_bpmedia[$i].Split(" ")[1]
        $MediaID = $NB_bpmedia[$i].Split(" ")[8]
        Write-Host "$CopyNumber" -ForegroundColor Red
        Write-Host "$MediaID" -ForegroundColor Green
        If($MediaID -like "*@aaaaz*"){
            $Image = $BID+"_C"+$CopyNumber | Out-file $ImageCatalog -Append
        }
      }
    Until($NB_bpmedia[$i] -like "*IMAGE*" -or $i -le $NbrLigne)
}

In fact Rob you make me on the good Way :wink:

Thx you both :wink:

Here’s my idea of a solution. I used your example to test, but changed one of the media IDs to make sure it works since none in your sample were @aaaac

$text=Get-Content -Raw .\search.txt
ForEach ($group in ($text -split "IMAGE " | Select-Object -Skip 1)) {
    $rows = $group -split [environment]::NewLine
    $image = [pscustomobject]@{
       Name = ($rows[0] -split " ")[0]
       BUID = ($rows[0] -split " ")[1]
    } #IMAGE
    ForEach ($line in ($rows | Select-Object -Skip 1)) {
        $frag = [pscustomobject]@{
            CopyNum = ($line -split " ")[1]
            FragNum = ($line -split " ")[2]
            MediaID = ($line -split " ")[8]
        } #frag object
        if ($frag.MediaID -eq "@aaaac") {
            "Backup-{0}_C{1}" -f $image.BUID, $frag.CopyNum | Out-File .\results.txt -Append
        } #if @aaaac
    } #foreach line
} #foreach group

 

 

I will test it Mike :wink:
Thx and have a nice day or evening :wink:

I have no idea how my post wound up here … I was replying to a completely different topic. DISREGARD this.

 

Hello Mike,

 

I have test your script and works fine ^^

Better than mine i think.

But i dont’ understand all :

 

 

$NB_bpmedia = "C:\Lab\Pogather-3.02_Win_64\NB_bpmedia.lst"
$ImageCatalog = "C:\Lab\ImageCatalog.txt"

If(Test-Path -path $ImageCatalog ){Remove-Item $ImageCatalog}

$text=Get-Content -Raw $NB_bpmedia
ForEach ($group in ($text -split "IMAGE "| Select-Object -Skip 1 )) {
    Write-Host "$group" 
    $rows = $group -split [environment]::NewLine
    $image = [pscustomobject]@{
       Name = ($rows[0] -split " ")[0]
       BUID = ($rows[0] -split " ")[2]
    } #IMAGE
    ForEach ($line in ($rows | Select-Object -Skip 1)) {
        $frag = [pscustomobject]@{
            CopyNum = ($line -split " ")[1]
            FragNum = ($line -split " ")[2]
            MediaID = ($line -split " ")[8]
        } #frag object
        if ($frag.MediaID -eq "@aaaaz") {
            "{0}_C{1}" -f $image.BUID, $frag.CopyNum | Out-File $ImageCatalog -Append
        } #if @aaaac
    } #foreach line
} #foreach group

Could you exlain to me what are doing the Select-Object -Skip 1
And after you call a Method $rows = $group -split [environment]::NewLine, could you explain this line what is this method.

Thx a lot.

-Skip 1 parameter/argument ignores the first item in the array. I do this on line 7 because

$text -split "IMAGE "

will produce an array with a null item in the first position. This is because the contents of the file starts with “IMAGE” and that is what we are splitting it on. Here is a simplified example that illustrates the issue.

PS C:\Users\micha> "Hello, World" -split "Hello"

, World

PS C:\Users\micha> "Hello, World" -split ","
Hello
 World

Notice when I split on “Hello” the first item in the array is empty and the second item is “, World”. This is because the string starts with the expression I am splitting on. The second example I split on “,” and since it is NOT the first item in the string, the first element in the array is “Hello” and the second element is " World"

On line 14 I use the skip for a different reason. On this line skipping the first item in the array will skip the IMAGE line leaving just the FRAG lines to process for the current IMAGE.