Join lines with powershell between files

Hello powershell friends .
First: Sorry for my bad english but I hope you understand what I meen.

This is my txt file (One separating spaces per line) - Example:

3/aaaaa 6
a/bbbbb 12
td/23d234f 101
t12s/65464dsf2 124
t5/rsdaad 161
124tz/weq 188
3ds/543 200
65aa/4423tz 225

Than I have split my txt file:

  1. TXT File
3/aaaaa
a/bbbbb
td/23d234f
t12s/65464dsf2
t5/rsdaad
124tz/weq
3ds/543
65aa/4423tz

and my second TXT file:

6
12
101
124
161
188
200
225

Ok. I have 2 new txt files.
Than I’m looking for numbers in the second file.
The solution write it to a third txt file .

12
101
124
161
188
200

No problem. I have now 3 files but how can I make this to one now?
That is what is needed in the end:

a/bbbbb 12
td/23d234f 101
t12s/65464dsf2 124
t5/rsdaad 161
124tz/weq 188
3ds/543 200

First I think I generate linenumber (first and second txt file) but this is not a option because
this make problems by my number search into the second file.
Not a option:

$Linenumbers =(Get-Content .\example.txt)
$a = 0
$Linenumbers | Foreach-Object { $a++; "" + $a + ": " + $_ }

I hope someone can tell me how the lines can be put back together.
I am a beginner with powershell. Sorry.

Thanks.

Venus642,
Welcome to the forum. :wave:t4:

I’m actually unsure what you mean with …

If I got it right you have only numbers in your second file.

But actually I wouldn’t work with files unless you need them for a particular reason. Here is an example how you can use the -split oparator using a white space as delimiter to split the lines into separate values and still keep the relation between the values of a line.

Get-Content -Path D:\sample\input.txt |
    ForEach-Object{
        $SplittedInput = $_ -split "\s+"
        [PSCustomObject]@{
            PartOne = $SplittedInput[0]
            PartTwo = $SplittedInput[1]
        }
    }

… you could even split the first part again with another delimiter :

Get-Content -Path D:\sample\input.txt |
ForEach-Object {
    $SplittedInput = $_ -split "\/|\s+"
    [PSCustomObject]@{
        PartOne   = $SplittedInput[0]
        PartTwo   = $SplittedInput[1]
        PartThree = $SplittedInput[2]
    }
}

Yes, thats right.

Thanks Olaf for your help!

Nochmal kurz zusammengefasst. Die TXT Datei wurde gesplittet, und die Zahlen nach dem Leerzeichen (muss dort sein) wurden in einer zweiten Datei gespeichert. Diese Datei dient dazu um nach Zahlen zu suchen, und wenn vorhanden, wird dieses Ergebnis in einer dritten Datei gespeichert. Das funktioniert soweit.

Es ist aber notwendig das Suchergebnis aus der dritten Datei mit der ersten Datei wieder zu verbinden,
um die ursprünglichen vollständigen Zeilen zu bekommen.

Beispiel:
Das Suchergebnis: ‘200’ aus der dritten Datei, mit der dazugehörigen Zeile aus der 1.TXT
‘3ds/543’ wird zu ‘3ds/543 200’ verbunden, und anschließend neu gespeichert.

Translate:
Again briefly summarized. The TXT file was split, and the numbers after the space (must be there)
were saved in a second file. This file is used to search for numbers and, if available,
this result is saved in a third file. That works so far.

However, it is necessary to reconnect the search result from the third file with the first file,
to get the original full lines.

Example:
The search result: ‘200’ from the third file, with the corresponding line from the 1st TXT
‘3ds / 543’ reconnected to ‘3ds / 543 200’, and then re-saved.

Unfortunately, that didn’t make it any better at all. :wink: Have you tried my code suggestion? Could it be possible that your sample data is not well chosen? How do you search for numbers in a file of only numbers?

Here again my code suggestion using your example data. Please try to run the code as it is.

$InputData = 
@'
3/aaaaa 6
a/bbbbb 12
td/23d234f 101
t12s/65464dsf2 124
t5/rsdaad 161
124tz/weq 188
3ds/543 200
65aa/4423tz 225
'@

$InputData -split "\n" |
    ForEach-Object {
    $SplittedInput = $_ -split "\s+"
    [PSCustomObject]@{
        PartOne   = $SplittedInput[0]
        PartTwo   = $SplittedInput[1]
    }
}

This code provides the output like this:

PartOne        PartTwo
-------        -------
3/aaaaa        6
a/bbbbb        12
td/23d234f     101
t12s/65464dsf2 124    
t5/rsdaad      161
124tz/weq      188
3ds/543        200
65aa/4423tz    225

As you can see the individual parts of the data from each line are still “related”. But now you can filter for the individual parts if you need.

There’s no need to if you don’t separate them. Or did I get something wrong again?

Hello Olaf.
Thanks again. Can you please say how I can extract
the ‘PartTwo’ specific column and store in a variable?

I have tested this one (example)

$test = $InputData | select -ExpandProperty PartTwo
or
$test = ($InputData).PartTwo

and more but all is not right.

Powershell Error:
select : Die PartTwo-Eigenschaft kann nicht gefunden werden.

I hope you have a idea.
Thanks

Well … I could. But actually I am pretty sure that it is not necessary. Could you please describe what your actual over all task is - not what you think you need to accomplish this task. I suspect that you overcomplicate this. :wink:

Fine Olaf.
How can I search within ‘PartTwo’ for 101 and 200.
And I found it: How can I save all lines from 101-200 (PartOne + PartTwo = td/23d234f 101) to a new txt file?
If I not found take for 200 (next higher) → 225, and for 101 (next lower) → 12
And the same. Save all lines 12 until 225 to a new txt file.

I hope anyone can say it. Thanks very mutch.

???

Search for what?

Did you find it or are you asking?

Describe it German if it’s too hard for you in english. What is the overall task you want to accomplish?

And BTW: will it take every time one day for you to answer? Is it your last action before you leave the office to come here and answer? :smirk:

1 Like

I’m looking for the numbers

Entschuldigung das mein Englisch so schlecht ist. Ich möchte die 2. Spalte “PartTwo” bzw. das Objekt gerne nach 2 Zahlen durchsuchen. Beispiel nach der Zahl 101 und 200 aus diesem Datensatz:

PartOne        PartTwo
-------        -------
3/aaaaa        6
a/bbbbb        12
td/23d234f     101
t12s/65464dsf2 124    
t5/rsdaad      161
124tz/weq      188
3ds/543        200
65aa/4423tz    225

Wenn beide Zahlen vorhanden sind, müssen alle Zahlen von 101 bis 200 mit dem jeweiligen Text / Zeile aus ‘PartOne’ als TXT gespeichert werden (z.B.: td/23d234f 101).

Angenommen es wird als erste gesuchte Zahl nach 102 gesucht, und diese ist nicht vorhanden, muss die nächstniedrigere (101), und bei der 2 gesuchten Zahl (z.B. bei 203) die nicht vorhanden ist die nächsthöhere (225) gewählt werden.

Es ist Ziel die Zeilen von z.B. 101 und 200 als TXT zu speichern.
So muss das Ergebnis aussehen:

td/23d234f     101
t12s/65464dsf2 124    
t5/rsdaad      161
124tz/weq      188
3ds/543        200

Oder wenn ggfs. die gesuchten Zahlen nicht gefunden werden, muss das ggf. ausgegeben werden:

td/23d234f     101
t12s/65464dsf2 124    
t5/rsdaad      161
124tz/weq      188
3ds/543        200
65aa/4423tz    225

Ich hoffe das die Fragestelle nachvollziehbar ist.

Nein, das ist nicht der Fall.

Don’t worry. :wink: We will keep on trying until you’re satisfied or give up. :stuck_out_tongue_winking_eye: :grin:

And maybe it’s me. It’s possible that I expect something what’s not there.

OK, let’s create our work data:

$WorkData = 
@'
3/aaaaa 6
a/bbbbb 12
td/23d234f 101
t12s/65464dsf2 124
t5/rsdaad 161
124tz/weq 188
3ds/543 200
65aa/4423tz 225
'@ -split "\n" |
ForEach-Object {
    $SplittedInput = $_ -split "\s+"
    [PSCustomObject]@{
        PartOne = $SplittedInput[0]
        PartTwo = $SplittedInput[1]
    }
}

Now, when you output

$WorkData

you get this:

PartOne        PartTwo
-------        -------
3/aaaaa        6
a/bbbbb        12
td/23d234f     101
t12s/65464dsf2 124
t5/rsdaad      161
124tz/weq      188
3ds/543        200
65aa/4423tz    225

Now we can filter for whatever condition you like (BTW: that’s the part I didn’t get yet completely :wink: )
Let’s say you want only the data set with 101 in PartTwo:

$WorkData | Where-Object -Property PartTwo -EQ -Value 101

or 200 in PartTwo:

$WorkData | Where-Object -Property PartTwo -EQ -Value 200

… or both …

$WorkData | Where-Object { [int]$_.PartTwo -eq 101 -or [int]$_.PartTwo -eq 200 }

… or you want all data sets where PartTwo is an integer between 101 and 200

$WorkData | Where-Object { [int]$_.PartTwo -ge 101 -and [int]$_.PartTwo -le 200 }

… of course you can do further steps with it … like rejoining with a space character:

$WorkData | 
    Where-Object { [int]$_.PartTwo -ge 101 -and [int]$_.PartTwo -le 200 } |
        ForEach-Object {
            $_.PartOne,$_.PartTwo -join ' '
        }

… and outputting it to a file:

$WorkData | 
    Where-Object { [int]$_.PartTwo -ge 101 -and [int]$_.PartTwo -le 200 } |
        ForEach-Object {
            $_.PartOne,$_.PartTwo -join ' '
        } |
            Out-File -FilePath .\output.txt

That’s the difficult part … to create proper conditions. And you should be sure about ALL needed conditions in advance.

:+1:t4: :metal:t4:

BTW: Sometimes it’s easier to ask complex questions in your native language. There are German forums for PowerShell questions as well.

https://social.technet.microsoft.com/Forums/de-DE/home?forum=powershell_de

2 Likes

Olaf you are my hero! Best best thanks.

I was looking for that! -Super!

$WorkData = 
@'
3/aaaaa 6
a/bbbbb 12
td/23d234f 101
t12s/65464dsf2 124
t5/rsdaad 161
124tz/weq 188
3ds/543 200
65aa/4423tz 225
'@ -split "\n" |
ForEach-Object {
    $SplittedInput = $_ -split "\s+"
    [PSCustomObject]@{
        PartOne = $SplittedInput[0]
        PartTwo = $SplittedInput[1]
    }
}
$WorkData


$WorkData | 
    Where-Object { [int]$_.PartTwo -ge 101 -and [int]$_.PartTwo -le 188 } |
        ForEach-Object {
            $_.PartOne,$_.PartTwo -join ' '
        }

$WorkData | 
    Where-Object { [int]$_.PartTwo -ge 101 -and [int]$_.PartTwo -le 188 } |
        ForEach-Object {
            $_.PartOne,$_.PartTwo -join ' '
        } |
            Out-File -FilePath .\output.txt

That was exactly one point that I didn’t understand how to declare

 $_.PartOne,$_.PartTwo -join ' '

Unimaginable when I look at the short script how much time I have already invested in it and without success.

Last question with numbers that are not in ‘PartTwo’

$WorkData | 
    Where-Object { [int]$_.PartTwo -ge 103 -and [int]$_.PartTwo -le 189 } |
        ForEach-Object {
            $_.PartOne,$_.PartTwo -join ' '
        }

Result - Uses the next higher number, and the next lower number:

t12s/65464dsf2 124
t5/rsdaad 161
124tz/weq 188

Why don’t you get a result when:

$WorkData | 
    Where-Object { [int]$_.PartTwo -le 103 -and [int]$_.PartTwo -ge 189 } |
        ForEach-Object {
            $_.PartOne,$_.PartTwo -join ' '
        }

-le less than or equal to and -ge greater than or equal to is needed

That is needed:

td/23d234f     101
t12s/65464dsf2 124
t5/rsdaad      161
124tz/weq      188
3ds/543        200

Olaf ein ganz tolles Skript

That’s what I meant. The more conditions you want to be checked the more complex will the code be. Because you have to check all elements for this kind of condition in advance you have to do it before you actually use the pipeline to run through the elements one by one.

(Das meinte ich. Je mehr voneinander abhängige Bedingungen Du prüfen möchtest, desto komplexer wird der Code. Und bei solchen Bedingungen musst Du erstmal alle Elemente prüfen, bevor Du sie mittels der Pipeline durchhühnern kannst - und das jeweils einmal für den Startwer und einmal für den Endwert.)

$StartValue = 110
$EndValue = 195

$WorkData = 
@'
3/aaaaa 6
a/bbbbb 12
td/23d234f 101
t12s/65464dsf2 124
t5/rsdaad 161
124tz/weq 188
3ds/543 200
65aa/4423tz 225
'@ -split "\n" |
    ForEach-Object {
        $SplittedInput = $_ -split "\s+"
        [PSCustomObject]@{
            PartOne = $SplittedInput[0]
            PartTwo = $SplittedInput[1]
        }
    }

if ( [int[]]$WorkData.PartTwo -notcontains $StartValue ) {
    $StartValueSubstitute =
        [int[]]$WorkData.PartTwo | 
            Where-Object { $_ -lt $StartValue } |
                Sort-Object |
                    Select-Object -Last 1
    $StartValue = $StartValueSubstitute
}

if ( [int[]]$WorkData.PartTwo -notcontains $EndValue ) {
    $EndValueSubstitute =
        [int[]]$WorkData.PartTwo | 
            Where-Object { $_ -gt $EndValue } |
                Sort-Object |
                    Select-Object -First 1
    $EndValue = $EndValueSubstitute
}

$WorkData | 
    Where-Object { [int]$_.PartTwo -ge $StartValue -and [int]$_.PartTwo -le $EndValue } |
        ForEach-Object {
            $_.PartOne, $_.PartTwo -join ' '
        } |
            Out-File -FilePath .\output.txt

For you or for me? :smirk: :stuck_out_tongue_winking_eye: :santa:t4: :santa:t4:

2 Likes

Natürlich auch für dich.
Meine letzte Frage hat sich gerade überschnitten…

Genau das hatte ich noch gesucht.
Endlich, Endlich. Vielen, Vielen DANK!
Ich bedanke mich ganz herzlich für deine tolle Hilfe,
und wünsche Dir alles GUTE!!!

Of course for you too.
My last question just overlapped …

That was exactly what I was looking for.
Finally, finally. Thanks alot!
I thank you very much for your great help,
and wish you all the best!