Powershell: Read Text file line by line and split on "|"
Asked Answered
J

3

6

I am having trouble splitting a line into an array using the "|" in a text file and reassembling it in a certain order. There are multiple lines like the original line in the text file.

This is the original line:

80055555|Lastname|Firstname|AidYear|DCDOCS|D:\BDMS_UPLOAD\800123456_11-13-2018 14-35-53 PM_1.pdf

I need it to look this way:

80055555|DCDOCS|Lastname|Firstname|AidYear|D:\BDMS_UPLOAD\800123456_11-13-2018 14-35-53 PM_1.pdf

Here is the code I am working with:

$File = 'c:\Names\Complete\complete.txt'
$Arr = $File -split '|'
foreach ($line in Get-Content $File)
{
  $outputline = $Arr[0] + "|" + $Arr[4] + "|" + $Arr[1] + "|" + $Arr[2] + "|" + 
    "@@" + $Arr[5] |
      Out-File -filepath "C:\Names\Complete\index.txt" -Encoding "ascii" -append 
}
Josselyn answered 13/12, 2018 at 15:14 Comment(0)
I
4

You need to process every line of the file on its own and then split them.

$File = get-content "D:\test\1234.txt"
foreach ($line in $File){
    $Arr = $line.Split('|')
    [array]$OutputFile +=  $Arr[0] + "|" + $Arr[4] + "|" + $Arr[1] + "|" + $Arr[2] + "|" + "@@" + $Arr[5] 
}
$OutputFile | out-file -filepath "D:\test\4321.txt" -Encoding "ascii" -append 

edit: Thx to LotPings for this alternate suggestion based on -join and the avoidance of += to build the array (which is inefficient, because it rebuilds the array on every iteration):

$File = get-content "D:\test\1234.txt"
$OutputFile = foreach($line in $File){($line.split('|'))[0,4,1,2,3,5] -Join '|'}
$OutputFile | out-file -filepath "D:\test\4321.txt" -Encoding "ascii"
Inez answered 13/12, 2018 at 15:31 Comment(0)
B
2

Since your input file is actually a CSV file without headers and where the fields are separated by the pipe symbol |, why not use Import-Csv like this:

$fileIn  = 'C:\Names\Complete\complete.txt'
$fileOut = 'C:\Names\Complete\index.txt'
(Import-Csv -Path $File -Delimiter '|' -Header 'Item','LastName','FirstName','AidYear','Type','FileName' | 
    ForEach-Object {
        "{0}|{1}|{2}|{3}|{4}|{5}" -f $_.Item, $_.Type, $_.LastName, $_.FirstName, $_.AidYear, $_.FileName
    }
) | Add-Content -Path $fileOut -Encoding Ascii
Burck answered 13/12, 2018 at 16:12 Comment(1)
Super! It worked perfectly! I will add this to my toolkit for future use as well!Josselyn
P
2

To offer a more PowerShell-idiomatic solution:

# Sample input line.
$line = '80055555|Lastname|Firstname|AidYear|DCDOCS|D:\BDMS_UPLOAD\800123456_11-13-2018 14-35-53 PM_1.pdf'

# Split by '|', rearrange, then re-join with '|'
($line -split '\|')[0,4,1,2,3,5] -join '|'

Note how PowerShell's indexing syntax (inside [...]) is flexible enough to accept an arbitrary array (list) of indices to extract.

Also note how -split's RHS operand is \|, i.e., an escaped | char., given that | has special meaning there, because it is interpreted as a regex.

To put it all together:

$File = 'c:\Names\Complete\complete.txt'
Get-Content $File | ForEach-Object {
  ($_ -split '\|')[0,4,1,2,3,5] -join '|'
} | Out-File -LiteralPath C:\Names\Complete\index.txt -Encoding ascii

As for what you tried:

$Arr = $File -split '|'

Primarily, the problem is that the -split operation is applied to the input file path, not to the file's content.

Secondarily, as noted above, to split by a literal | char., \| must be passed to -split, because it expects a regex (regular expression).

Also, instead of using Out-File inside a loop with -Append, it is more efficient to use a single pipeline with ForEach-Object, as shown above.

Pushover answered 14/12, 2018 at 0:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.