Delete a line in txt file after a specific keyword - powershell

I have a txt file like:
sample text1
sample text2
sample text3
and I need it to be:
sample
sample
sample
Basically, I need to delete the entire line after a given phrase, in this case the "sample" keyword
Can someone help me? I would prefer vbscript or something that is stanalone and I can make a batch for this
Regards,

(Get-Content sample.txt) -replace '.*sample(.+)', '$1' | Out-File sample.txt

This will work inside a .cmd or .bat file:
for /f "tokens=1" %%i in ('type file1') do #echo %i >> file2

Since you tagged your question with powershell, I'll give you a solution in powershell:
$target='sample'
foreach ($line in gc .\foo.txt){$line.substring(0,$target.length)|out-file -append bar.txt}
I assume that every line starts with "sample".
If the "sample" text is anywhere in the line, this should work:
$target='sample'
foreach ($line in gc .\foo.txt){$line.substring(0,$line.indexof($target)+$target.length)|out-file -append bar.txt}

With Just Vbscript, you can achieve this as follows
Option Explicit
Dim oFSO, oTxtFile, sLine ,filePath, cTxtFile
Const ForReading=1
Const ForWriting=2
filePath ="C:\Documents and Settings\Amol\Desktop\Converted\test.txt"
'' Filepath is your local path to txt file
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oTxtFile = oFSO.OpenTextFile(filePath, 1)
Set cTxtFile = oFSO.CreateTextFile(filePath & ".tmp")
Do Until oTxtFile.AtEndOfStream
sLine = oTxtFile.ReadLine
If InStr(sLine,"sample") <> 0 Then
sLine = Left(sLine, InStr(sLine,"sample") -1 )&"sample"
cTxtFile.WriteLine(sLine)
End if
Loop
oTxtFile.Close
cTxtFile.Close
oFSO.DeleteFile(filePath)
oFSO.MoveFile filePath&".tmp", filePath

Related

How do I make PowerShell read a file as single lines when it thinks there are multiple lines?

I have an input file with the following lines:
1000095710|SavRx
1000124602|Mason’s Pharmacy
1001130436|Regence
1001314900|HealthE Systems
1001322929|IT management
Which I created with the the line:
$line = $numValueYouSee + "|" + $fd.Replace("Client", "") #Client used to say ClientNameOfClientYouSeeNowAsSavRx
When I read the new output file with PowerShell using $FileText = gc "Path\To\File.txt", it is reading the lines as the following:
1000095710
|SavRx
1000124602
|Mason’s Pharmacy
1001130436
|Regence
1001314900
|HealthE Systems
1001322929
|IT management
I can verify the lines of the file by just clicking arrow keys, but in Notepad++ I can see extra CR-LFs. How can I fix this ridiculous output to the correct output?
Looks to me like your data fields have trailing CR characters. Demonstration:
PS C:\Temp> $s = "1000095710`r|SavRx`r`r`n1000124602`r|Mason's Pharmacy`r`r`n"
PS C:\Temp> [IO.File]::WriteAllText('c:\temp\out.txt', $s)
PS C:\Temp> Get-Content .\out.txt
1000095710
|SavRx
1000124602
|Mason's Pharmacy
You can remove them by trimming your fields before creating the output.
$line = $numValueYouSee.Trim() + "|" + $fd.Replace("Client", "").Trim()
I cannot replicate your issue either. Maybe you have to save your file again from notepad. Maybe there is hidden formatting in the text like a hidden "`n"
You could try this:
$FileText = Import-Csv Path\To\File.txt -Header Number,Type -Delimiter "|" -Encoding Default

Using PowerShell in a .bat file, replace a string with multiple strings

I'm using a .baat to move several files into another folder, but before the actual move part, I want to replace the LAST line (it is a known line), for example I have a file output.txt like this:
HEADER
BODY
FOOTER
Using this snippet of code:
powershell -Command "(gc output.txt) -replace 'FOOTER', 'ONE_MORE_LINE `r`n FOOTER' | Out-File output.txt"
The return that I expected was
HEADER
BODY
ONE_MORE_LINE
FOOTER
But what I got was:
HEADER
BODY
ONE_MORE_LINE `r`n FOOTER
I've tried:
\n
<br>
"`r`n"
"`n"
echo ONE_MORE_LINE >> output.txt; echo. >> output.txt; echo FOOTER >> output.txt"
This last one got close, but the result was some broken characters.
Other suggestions besides the PowerShell are welcome. I'm only using it because it was an easy get way to do the adding lines and replace it.
EDIT :
Tried this command
powershell -Command "(gc output.txt) -replace 'FOOTER;', ""ONE_MORE_LINE `r`n FOOTER"" | Out-File output.txt "
And returned this error:
A cadeia de caracteres não tem o terminador: ".
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
EDIT2 - Possible Solution:
I realized that using the PowerShell command altered the encoding of the file, breaking the echo ONE_MORE_LINE, and using the suggestion from #AnsgarWiechers, I made this code
findstr /v "FOOTER" output.sql > new_output.sql
TYPE new_output.sql > output.sql
del new_output.sql
ECHO. >> %%f
ECHO ONE_MORE_LINE >> %%f
ECHO FOOTER >> %%f
ECHO. >> %%f
What it does is using the commant findstr /v "FOOTER" I look for all lines that are not FOOTER in the file output.sql and Write it on new_output.sql
Then I TYPE it back to the original file, and DEL the new_output.sql
Then I Echo all the lines I need right under it.
It works BUT, for big files I think that re-writing it twice will take a lot of time, but I can't figure an other solution.
When working with big files it's best to use a file stream. More typical methods of reading a file line-by-line using a Batch for /f loop or using Get-Content in PowerShell to read the entire file into memory can slow the process to a crawl with large files. Using a file stream on the other hand, you can nearly instantly seek back from the end of the file to the beginning of the last line, insert your desired data, and then reassemble the bytes you overwrote.
The following example will use PowerShell's access to .NET methods to open a file as a byte stream for rapid reading and writing. See inline comments for details. File encoding will hopefully be preserved. Save this with a .bat extension and give it a shot.
<# : batch portion
#echo off & setlocal
set "file=test.txt"
set "line=Line to insert!"
powershell -noprofile "iex (${%~f0} | out-string)"
goto :EOF
: end batch / begin PowerShell hybrid #>
# construct a file stream for reading and writing $env:file
$IOstream = new-object IO.FileStream((gi $env:file).FullName,
[IO.FileMode]::OpenOrCreate, [IO.FileAccess]::ReadWrite)
# read BOM to determine file encoding
$reader = new-object IO.StreamReader($IOstream)
[void]$reader.Read((new-object byte[] 3), 0, 3)
$encoding = $reader.CurrentEncoding
$reader.DiscardBufferedData()
# convert line-to-insert to file's native encoding
$utf8line = [Text.Encoding]::UTF8.GetBytes("`r`n$env:line")
$line = [Text.Encoding]::Convert([Text.Encoding]::UTF8, $encoding, $utf8line)
$charSize = [math]::ceiling($line.length / $utf8line.length)
# move pointer to the end of the stream
$pos = $IOstream.Seek(0, [IO.SeekOrigin]::End)
# walk back pointer while stream returns no error
while ($char -gt -1) {
$IOstream.Position = --$pos
$char = $reader.Peek()
$reader.DiscardBufferedData()
# break out of loop when line feed preceding non-whitespace is found
if ($foundPrintable) { if ($char -eq 10) { break } }
else { if ([char]$char -match "\S") { $foundPrintable++ } }
}
# step pointer back to carriage return and read to end into $buffer with $line prepended
$pos -= $charSize
$IOstream.Position = $pos
$buffer = $encoding.GetBytes($encoding.GetString($line) + $reader.ReadToEnd())
$IOStream.Position = $pos
"Inserting data at byte $pos"
$IOstream.Write($buffer, 0, $buffer.Length)
# Garbage collection
$reader.Dispose()
$IOstream.Dispose()
This method should be much more efficient than reading the file from the beginning, or copying the entire file into memory or on disk with a new line inserted. In my testing, it inserts the line into a hundred meg file in about 1/3 of a second.

Remove all carriage return and line feed from file

Last week I have asked you guys to replace a string with newline character with .bat script. I have realized that my file has some carriage return and newline characters already, which I need to remove first and then do the replace.
to replace '#####' with linefeed I am using the line below.
(gc $Source) -replace "#####", "`r`n"|set-content $Destination
So I tried to implement the same logic to replace \r and \n as well, however it did not work.
(gc $Source) -replace "`n", ""|set-content $Destination
my file looks like :
abc|d ef|123#####xyz|tuv|567#####
and I need to make it look like
abc|def|123 xyz|tuv|567
like I said, replacing the row delimiter character with new line works, but I need to remove all cr and lf characters first before I do that.
For small files the script below works, but my file is >1.5GB and it throws OutofMemoryException error
param
(
[string]$Source,
[string]$Destination
)
echo $Source
echo $Destination
$Writer = New-Object IO.StreamWriter $Destination
$Writer.Write( [String]::Join("", $(Get-Content $Source)) )
$Writer.Close()
Use the below function to remove the special characters. Put all of them in $SpecChars what ever you want to remove and call the function with the Text-data as a parameter.
Function Convert-ToFriendlyName
{param ($Text)
# Unwanted characters (includes spaces and '-') converted to a regex:
#Whatever characters you want to remove, put it here with comma separation.
$SpecChars = '\', ' ','\\','-'
$remspecchars = [string]::join('|', ($SpecChars | % {[regex]::escape($_)}))
# Convert the text given to correct naming format (Uppercase)
$name = (Get-Culture).textinfo.totitlecase(“$Text”.tolower())
# Remove unwanted characters
$name = $name -replace $remspecchars, ""
$name
}
Hope it helps...!!!
This is vbscript. Windows isn't consistent. Mostly it breaks on CR and removes LF (all inbuilt programming languages). But Edit controls (ie Notepad) break on LF and ignore CR (unless preceding a LF).
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
Do Until Inp.AtEndOfStream
Text = Inp.readall
Text = Replace(Text, vbcr, "")
Text = Replace(Text, vblf, "")
Text = Replace(Text, "#####", vblf)
outp.write Text
Loop
This uses redirection of StdIn and StdOut.
Filtering the output of a command
YourProgram | Cscript //nologo script.vbs > OutputFile.txt
Filtering a file
Cscript //nologo script.vbs < InputFile.txt > OutputFile.txt
See my CMD Cheat Sheet about the Windows' command line Command to run a .bat file
So this removes line ending in win.ini and prints to screen the now one line win.ini.
cscript //nologo "C:\Users\David Candy\Desktop\Replace.vbs" < C:\windows\win.ini

how vbscript read the result file generated by powershell script (called by the vbscript itself) ?

I have one vbscript to execute a powershell script.
The powershell script simply append the result to a file.
Then after the powershell script execution complete and return to vbscript.
The vbscript will read content of the file and display it on console.
Unfortunately the powershell cannot generate the result file to be read by the vbscript.
If I change the line to ErrCode = objShell.run("powershell.exe -file writeFile.Ps1", 0),
The powershell script can generate the result file.
But the vbscript can never display the content of the result file correctly or it is corrupted.
If I open the result file from Notepad, I can view the content correctly.
Do you have any idea what is the problem behind?
Here are the source code:
Source code for readFile.vbs:\
resultFile = "writeFile.Ps1.txt"
set objShell = CreateObject("WScript.Shell")
ErrCode = objShell.run("powershell.exe -nologo -command writeFile.Ps1", 0)
Set objReadFile = CreateObject("Scripting.FileSystemObject")
Set strLines = objReadFile.OpenTextFile(resultFile, 1)
Do While Not strLines.AtEndOfStream
strLine = strLines.ReadLine()
WScript.Echo strLine
Loop
Set objReadFile = Nothing
Source code for writeFile.Ps1:
$ResultFilePath = "writeFile.Ps1.txt"
If (Test-Path $ResultFilePath) {
Remove-Item $ResultFilePath
}
Get-Date | out-file $ResultFilePath
Exit 0
Thanks.
On the Out-File, try using the parameter "-Encoding ASCII". By default Out-File outputs in Unicode.
Either make PowerShell create the file with ASCII encoding as Keith Hill suggested:
Get-Date | Out-File $ResultFilePath -Encoding ASCII
or open it as Unicode in VBScript:
Set strLines = objReadFile.OpenTextFile(resultFile, 1, False, -1)

Find and replace at powershell

My textfile looks like this:
-------------------
Set PRGVER="V1.0.12"
Set PRGDIR=C:\PRGSTD\oif_mes\OIFplus
Set PRGEXE=OIFplus.bat
Set PRGTXT=OIFplus
echo %PRGTXT%, %PRGVER%
start "%PRGTXT%" /D%PRGDIR%\%PRGVER%\ %PRGDIR%\%PRGVER%\%PRGEXE%
----------------------
What I wan't to do, edit this file, only change Set PRGVER="V1.0.12" to a new number, like this Set PRGVER=V1.0.13".
When is start the PS Script, I don't know the whole string, the number between "".
I only know, find string variable: Set PRGVER="".
How can I replace only the first value between ""?
Something like this;
$srt = <your text>
$r = $str -replace "PRGVER=`".*`"", "PRGVER=`"your_replace`""
The following should do it. It finds the a line that starts with 'Set PRGVER="V', followed by any number of digits, then a dot, any number of digits, a dot, any number of digits, and ends with '"'. When found, the line is replaced with 'Set PRGVER="V1.0.13"' and the result is saved back to the file.
(Get-Content file.txt) -replace '^Set PRGVER="V\d+\.\d+.\d+"$','Set PRGVER="V1.0.13"' | Out-File file.txt
Following PoSH will replace PRGVER value:
$newValue = "v123.456.789"
gc D:\temp\text | % { $_ -ireplace '(Set PRGVER=)\"([^"]*)\"', ('$1"' + $newValue + '"') };
You using key: Ctrl + H
More information: https://learn.microsoft.com/en-us/powershell/scripting/windows-powershell/ise/keyboard-shortcuts-for-the-windows-powershell-ise?view=powershell-7