How can I iterate through a .text file, starting from the end using Windows Powershell? - powershell

I want to go through a .txt/.log file line by line (with powershell). I have to start at the last line and make my way up to a specific line.
Can somebody help me with this?

Read the file with Get-Content, reverse the array and iterate trough it:
$content = Get-Content -Path "C:\path\to\my\file.txt"
[array]::Reverse($content)
$content | foreach {
$_ # Do something...
}

There are many ways to achieve this. Here is the basic iteration:
#'
Hello
Cruel
World
'# | Out-File demo-file.txt
$content = Get-Content demo-file.txt
for ($lineNumber = $content.Length-1; $lineNumber -ge 0; $lineNumber--) {
"$content[$lineNumber]"
}

Related

Powershell, replace string line by line in a textfile

I have a file called "file123624.TXT" that contains this information:
FKHOGU1100;;;;;;;;;;;;;randomdata;1;0;2;1234
YJKMRI1101;;;;;;;;;;;;;randomdata;1;0;2;1234
FWPCYY1113;GV;randomdata;5;;;;;;;6018;randomdata;GU;;1;0;2;1234
VOBYTM1100;;;;;;;;;;;;;randomdata;1;0;2;1234
ZSOKHW1160;GV;randomdata;53;;;;;;;7353;randomdata;GU;;1;0;2;1234
YCHQHS1123;GV;randomdata;4;;;;;;;5063;randomdata;GU;;1;0;2;1234
YXRCZO1105;GV;randomdata;39;;;;;;;9510;randomdata;GU;;1;0;2;1234
XVDUEM1100;GV;randomdata;14;;;;;;;9901;randomdata;GU;;1;0;2;1234
CHECKSUM;0000008
All i want to do is add an - after the first six characters in the file, except for the last line "CHECKSUM; 0000008"
I have made a small powershell script that almost does the trick:
$file = Get-Content "C:\Users\usr\Desktop\file*.txt"
foreach ($i in $file)
{
if($i -notmatch "CHECKSUM*")
{$I.Insert(6,'-')}
}
This script output the lines i need to be changed, but i cant replace them line for line.
The result i want in the "file123624.txt" after running the script is this:
FKHOGU-1100;;;;;;;;;;;;;randomdata;1;0;2;1234
YJKMRI-1101;;;;;;;;;;;;;randomdata;1;0;2;1234
FWPCYY-1113;GV;randomdata;5;;;;;;;6012;randomdata;GU;;1;0;2;1234
VOBYTM-1100;;;;;;;;;;;;;randomdata;1;0;2;1234
ZSOKHW-1160;GV;randomdata;53;;;;;;;7653;randomdata;GU;;1;0;2;1234
YCHQHS-1123;GV;randomdata;4;;;;;;;5463;randomdata;GU;;1;0;2;1234
YXRCZO-1105;GV;randomdata;39;;;;;;;9210;randomdata;GU;;1;0;2;1234
XVDUEM-1100;GV;randomdata;14;;;;;;;9401;randomdata;GU;;1;0;2;1234
CHECKSUM;0000008
Any solutions or tips on this would be appreciated
You can do the following, which utilizes the Foreach-Object and has a similar structure to your current code.
$file = Get-Content file123624.TXT | Foreach-Object {
if ($_ -notmatch '^CHECKSUM') {
$_.Insert(6,'-')
}
else {
$_
}
}
$file | Set-Content file123624.TXT

Pulling a substring for each line in file

Using Powershell, I am simply trying to pull 15 characters starting from the 37th position of any record that begins with a 6. I'd like to loop through and generate a record for each instance so it can later be put into an output file. But I seem to not be hitting the correct syntax just to return the 15 characters I know I am missing something obvious. Been at this for a while. Here is my script:
$content = Get-Content -Path .\tmfhsyst*.txt | Where-Object { $_.StartsWith("6") }
foreach ($line in $contents)
{
$val102 = $line.substring(36,15)
}
write-output $val102
Just as Bill_Stewart pointed out, you need to move your Write-Output line inside the ForEach loop. A possibly better way to do it would just be to pipe it:
Get-Content -Path .\tmfhsyst*.txt | Where-Object { $_.StartsWith("6") } | foreach{$_.substring(36,15)}
That should give you the output you desired.
Using Substring() has the disadvantage that it will raise an error if the string is shorter than start index + substring length. You can avoid this with a regular expression match:
(Get-Content -Path .\tmfhsyst*.txt) -match '^6.{35}(.{15})' | % { $matches[1] }

Powershell. Writing out lines based on string within the file

I'm looking for a way to export all lines from within a text file where part of the line matches a certain string. The string is actually the first 4 bytes of the file and I'd like to keep the command to only checking those bytes; not the entire row. I want to write the entire row. How would I go about this?
I am using Windows only and don't have the option to use many other tools that might do this.
Thanks in advance for any help.
Do you want to perform a simple "grep"? Then try this
select-string .\test.txt -pattern "\Athat" | foreach {$_.Line}
or this (very similar regex), also writes to an outfile
select-string .\test.txt -pattern "^that" | foreach {$_.Line} | out-file -filepath out.txt
This assumes that you want to search for a 4-byte string "that" at the beginning of the string , or beginning of the line, respectively.
Something like the following Powershell function should work for you:
function Get-Lines {
[cmdletbinding()]
param(
[string]$filename,
[string]$prefix
)
if( Test-Path -Path $filename -PathType Leaf -ErrorAction SilentlyContinue ) {
# filename exists, and is a file
$lines = Get-Content $filename
foreach ( $line in $lines ) {
if ( $line -like "$prefix*" ) {
$line
}
}
}
}
To use it, assuming you save it as get-lines.ps1, you would load the function into memory with:
. .\get-lines.ps1
and then to use it, you could search for all lines starting with "DATA" with something like:
get-lines -filename C:\Files\Datafile\testfile.dat -prefix "DATA"
If you need to save it to another file for viewing later, you could do something like:
get-lines -filename C:\Files\Datafile\testfile.dat -prefix "DATA" | out-file -FilePath results.txt
Or, if I were more awake, you could ignore the script above, use a simpler solution such as the following one-liner:
get-content -path C:\Files\Datafile\testfile.dat | select-string -Pattern "^DATA"
Which just uses the ^ regex character to make sure it's only looking for "DATA" at the beginning of each line.
To get all the lines from c:\somedir\somefile.txt that begin with 'abcd' :
(get-content c:\somedir\somefile.txt) -like 'abcd*'
provided c:\somedir\somefile.txt is not an unusually large (hundreds of MB) file. For that situation:
get-content c:\somedir\somefile.txt -readcount 1000 |
foreach {$_ -like 'abcd*'}

Powershell search through two lines

I have following Input lines in my notepad file.
example 1 :
//UNION TEXT=firststring,FRIEND='ABC,Secondstring,ABAER'
example 2 :
//UNION TEXT=firststring,
// FRIEND='ABC,SecondString,ABAER'
Basically, one line can span over two or three lines. If last character is , then it is treated as continuation character.
In example 1 - Text is in one line.
In example 2 - same Text is in two lines.
In example 1, I can probably write below code. However, I do not know how to do this if 'Input text' spans over two or three lines based on continuation character ,
$result = Get-Content $file.fullName | ? { ($_ -match firststring) -and ($_ -match 'secondstring')}
I think I need a way so that I can search text in multipl lines with '-and' condition. something like that...
Thanks!
You could read the entire content of the file, join the continued lines, and then split the text line-wise:
$text = [System.IO.File]::ReadAllText("C:\path\to\your.txt")
$text -replace ",`r`n", "," -split "`r`n" | ...
# get the full content as one String
$content = Get-Content -Path $file.fullName -Raw
# join continued lines, split content and filter
$content -replace '(?<=,)\s*' -split '\r\n' -match 'firststring.+secondstring'
If file is large and you want to avoid loading entire file into memory you might want to use good old .NET ReadLine:
$reader = [System.IO.File]::OpenText("test.txt")
try {
$sb = New-Object -TypeName "System.Text.StringBuilder";
for(;;) {
$line = $reader.ReadLine()
if ($line -eq $null) { break }
if ($line.EndsWith(','))
{
[void]$sb.Append($line)
}
else
{
[void]$sb.Append($line)
# You have full line at this point.
# Call string match or whatever you find appropriate.
$fullLine = $sb.ToString()
Write-Host $fullLine
[void]$sb.Clear()
}
}
}
finally {
$reader.Close()
}
If file is not large (let's say < 1G) Ansgar Wiechers answer should do the trick.

Powershell V2 find and replace

I am trying to change dates programmatically in a file. The line I need to fix looks like this:
set ##dateto = '03/15/12'
I need to write a powershell V2 script that replaces what's inside the single quotes, and I have no idea how to do this.
The closest I've come looks like this:
gc $file | ? {$_ -match "set ##dateto ="} | % {$temp=$_.split("'");$temp[17]
=$CorrectedDate;$temp -join ","} | -outfile newfile.txt
Problems with this: It gives an error about the index 17 being out of range. Also, the outfile only contains one line (The unmodified line). I'd appreciate any help with this. Thanks!
You can do something like this ( though you may want to handle the corner cases) :
$CorrectedDate = '10/09/09'
gc $file | %{
if($_ -match "^set ##dateto = '(\d\d/\d\d/\d\d)'") {
$_ -replace $matches[1], $CorrectedDate;
}
else {
$_
}
} | out-file test2.txt
mv test2.txt $file -force