How do edit the last occurrence of a particular string in powershell - powershell

My text file contains G-Code with the code "G94" appearing 5 times at different line numbers.
G94
G94
G94
G94
G94
I need to change the last occurrence of "G94" to
G94
/M16
but I keep getting no edit at all.
I'm trying this:
$text = get-content C:\cncm\g94.txt
$i = 1
$replace = 5 #Replace the 5th match
ForEach ( $match in ($text | select-String "G94" -AllMatches).matches)
{
$index = $match.Index
if ( $i -eq $replace )
{
$text.Remove($index,"G94".length).Insert($index,"G94 n /M16")
}
$i++
}
What am I missing?

$text is an array of strings, how are you calling Remove() without getting an exception? First because Remove() only takes one parameter, second because you can't remove from a fixed length array.
I'm thinking:
$text = get-content C:\cncm\g94.txt
$fifthMatch = ($text | select-string "G94" -AllMatches)[4]
$line = $text[$fifthMatch.LineNumber]
$line = $line.Remove($fifthMatch.index,"G94".length).Insert($fifthMatch.index,"G94 `n /M16")
$text[$fifthMatch.LineNumber] = $line
$text | out-file c:\cncm\g942.txt

Use regexp with negative lookahead on a string that contains the entire file.
Replacing last occurrence in the entire file - (?s) DOTALL mode allows .* to span across new line characters:
$text = [IO.File]::ReadAllText('C:\cncm\g94.txt')
$text = $text -replace '(?s)G94(?!.*?G94)', "G94`n/M16"
Replacing last occurrence in every line - (?m) MULTILINE mode:
$text = [IO.File]::ReadAllText('C:\cncm\g94.txt')
$text = $text -replace '(?m)G94(?!.*?G94)', "G94`n/M16"

Related

How to cut specific characters in a string and save it to a new file?

I have a string, and I want to cut some characters and store it to a new file.
I tried this code, but it still error.
$a = ";Code=NB"
$b = $a -split "="
$b[1]
$Save = "[AGM]", "CR=JP", "LOC= $b[1]"| Out-File "C:\Users\Out.txt"
Try something like this:
$a = ";Code=NB"
$null, $b, $null = $a -split '=', 3
$b
$Save = "[AGM]", "CR=JP", "LOC= $b"| Out-File "C:\Users\Out.txt"
Something that would be easier to maintain would be this:
#Words to remove from string
$wordsToCut = "This","is"
#Phrase to remove words from
$phrase = "This is a test"
#Running through all words in words to remove
foreach ($word in $wordsToCut){
#Replace current word with nothing
$phrase = $phrase.Replace($word,"")
}
#Output end result
Write-Host $phrase
You would also use trim to remove any leading or trailing spaces. The above code outputs:
a test

Powershell Split String with "-" and number

$string = abc_test.txt-1234.xml
trying to split it "-" and any number,
so that
first part after split would be abc_test.txt
I tried below.
$new = $string -Split'(?=\d)'
$new[0]
Add the dash to your -split:
$new = $string -Split'(?=-\d)'

Extract the numbers at the end from a file name using perl

I am unable to extract the last digits in the filename and rename the file placing the digits at the beginning of the file.
Like suppose my file name is "Gen_TCC_TIF_2110_413010_L3TL_Ae6TL707285_371925.out"
I want to rename the file as "371925_Gen_TCC_TIF_2110_413010_L3TL_Ae6TL707285.out"
my $newFileName ='Gen_TCC_TIF_2110_413010_L3TL_Ae6TL707285_371925.out';
my ($digits) = $newFileName =~ /(\d+)/g;
my $newFileName_2="${digits}_Gen_TCC_TIF_2110_413010_L3TL_Ae6TL707285_371925.out"
try:
$newFileName =~ /(\d+)\.out/;
my $digits = $1;
my $newFileName_2=$digits."_Gen_TCC_TIF_2110_413010_L3TL_Ae6TL707285_371925.out";
(\d+)\.out/ should give you all Digits before .out
Try this:
$newFileName =~ s/(.*?)_(\d+)\.out/$2_$1\.out/;
Or
$newFileName =~ s/(.*?)_(\d+)(\.\w+)/$2_$1$3/;
You can do it with a single regex:
my $newFileName = 'Gen_TCC_TIF_2110_413010_L3TL_Ae6TL707285_371925.out';
my $newFileName_2 = $filename =~ s/(.*)_(\d+)(?=\.out)/$2_$1/r;
# or, for older Perl, use this instead:
(my $newFileName_2 = $filename) =~ s/(.*)_(\d+)(?=\.out)/$2_$1/;
# or, to modify directly the variable $newFileName:
$newFileName =~ s/(.*)_(\d+)(?=\.out)/$2_$1/;
Or if you want to get the digits (because you need them for something else), then you can do:
my ($digits) = $newFileName =~ /_(\d+)\.out/;
You were using /g modifier, which made your regex match all blocks of digits, which isn't what you wanted. (even worst, it was returning an array, but you were only keeping the first element (2110) in the scalar $digit )

Powershell - search for string, remove excess whitespace, print second field

I'm having a problem parsing some string data in powershell and need a little help. Basically I have an application command that doesn't output objects, rather string data.
a = is the item I'm searching for
b = is the actual ouput from the command
c = replaces all the excess whitespace with a single space
d = is supposed to take $c "hostOSVersion 8.0.2 7-Mode" and just print "8.0.2 7-Mode"
However, $d is not working it just prints the same value as $c. I'm a UNIX guy and this would be easy in one awk statement. If you know how to do this in one command that would be nice, or just tell me what's wrong with my $d syntax below.
$a = "hostOSVersion"
$b = "hostOSVersion 8.0.2 7-Mode"
$c = ($a -replace "\s+", " ").Split(" ")
$d = ($y -replace "$a ", "")
Well you might have to futz around with the exact pattern, but one way is with a regex:
$b = "hostOSVersion 8.0.2 7-Mode"
$b -match '(\d.*)'
$c = $matches[1]
If you really wanted to oneline it with -replace:
$($($b -replace $a, '') -replace '\s{2}', '').trim()
Your line
$c = ($a -replace "\s+", " ").Split(" ")
should reference the $b variable instead of $a
$c = ($b -replace "\s+", " ").Split(" ")
Then, you will notice the output of $d becomes
hostOSVersion
8.0.2
7-Mode
and a statement like $d[1..2] -join ' ' would produce 8.0.2 7-Mode

another line split (powershell or other scripting tools under windows)

i have a log file in hand, looks like this:
0226 111641 (1911) 0 some space separated message containing whatever letters and marks
I need to import it to database, to use filters on it, when troubleshooting is needed. Currently i think powershell is best selection to achieve this, but i'm too green to know specifically how to do it so it can perform actually. I tried to do it like this:
$file = Get-Content "test.txt"
foreach ($line in $file)
{
#Write-Host $line
$a = $line
$month1 = $a[0..1]
$month2 = "$month1"
$month2 = $month2.ToString()
$month = $month2.Replace(" ", "")
$day1 = $a[2..3]
$day2 = "$day1"
$day2 = $day2.ToString()
$day = $day2.Replace(" ", "")
}
... and so on. after that inserting it to database. However, log file is quite big (currently 15MB in 3 weeks, expected to be hundreds of megabytes within months), and already the script takes about 4-5min to process it.
So what i need is method to split four space separated columns from beginning of the line, convert first and second to date and time and add them with message part of the line to database. Separately processing each block of text seems too time consuming, excel for example can process this file within seconds. Is there around some position aware csv-import command?
Thanks.
Found this:
Replace first two whitespace occurrences with a comma using sed
would help, if i would use linux... :(
I'm not sure if the ConvertFrom-Csv or Import-Csv cmdlets can help you since your field delimiter can appear in the message field. Without knowing what these different fields are, I came up with this:
$file = Get-Content "test.txt"
foreach ($line in $file)
{
# Split $line into at most 5 fields
$fields = $line -split ' ', 5;
# fields[0] is a two-digit month followed by a two-digit day
$date = [DateTime]::ParseExact($fields[0], 'MMdd', $null);
$field2 = $fields[1];
$field3 = $fields[2];
$field4 = $fields[3];
$message = $fields[4];
# Process variables here...
}
Using the sample text you provided for $line, the above variables look like this after execution:
PS> Get-Variable -Name #('date', 'field*', 'line', 'message')
Name Value
---- -----
date 2/26/2012 12:00:00 AM
field2 111641
field3 (1911)
field4 0
fields {0226, 111641, (1911), 0...}
line 0226 111641 (1911) 0 some space separated message
message some space separated message
More information will be needed on the format of your data in order to give you a more specific answer.