Solved

Can't get Powershell Script to work

Posted on 2016-10-31
16
100 Views
Last Modified: 2016-11-01
I have this script that I am trying to get to change all instances of  T101 to T102 and continue and do T103 to T102 plus a few more changes. Then save the file with the original name plus a _cnc3 at the end. That part I have working fine. The issue I'm having is below.
#CRMe.ps1
param( [string] $fileName)

# Check the file exists
if (-not(Test-Path $fileName)) {break}

# Display the original name
"Original filename: $fileName"

$fileObj = get-item $fileName

# Get the Add
$DateStamp = "_cnc3"
$extOnly = $fileObj.extension

if ($extOnly.length -eq 0) {
   $nameOnly = $fileObj.Name
(Get-Content $fileObj.Name) | ForEach-Object { $_ -replace "t101", "t102" ; "t103", "t102" ; "t1001", "t2002" }| Set-Content "$nameOnly-$DateStamp"
}
else {
   $nameOnly = $fileObj.Name.Replace( $fileObj.Extension,'')

(Get-Content $fileObj.Name) | ForEach-Object { $_ -replace "t101", "t102" ; "t103", "t102" ; "t1001", "t2002" }| Set-Content "$nameOnly$DateStamp$extOnly"
}

Open in new window

I call this script in the folder that I am working in with this script
foreach ($file in get-ChildItem *.txt) { ./CRMe.ps1 $file.name }

write-host "Press any key to continue..."
[void][System.Console]::ReadKey($true)

Open in new window

However when I run the code on my sample it gives me additional lines and does not change anything. If I run only one set { $_ -replace "t101", "t102"} it runs fine and changes the line of text.

Original Text
hfyjhfhjkT101
T101gfyfyf
t1001fdsaf
t103fsdafsd

Exported Text
hfyjhfhjkT101
hfyjhfhjkT101
hfyjhfhjkT101
T101gfyfyf
T101gfyfyf
T101gfyfyf
t1001fdsaf
t1001fdsaf
t1001fdsaf
t103fsdafsd
t103fsdafsd
t103fsdafsd


So what do I need to change in the powershell script to not add additional lines and actually just change the text.
0
Comment
Question by:bobgraf
  • 5
  • 3
  • 3
  • +2
16 Comments
 
LVL 14

Expert Comment

by:Jason Crawford
Comment Utility
I can't say this is specifically what's causing the behavior you're reporting, but I do find it odd you're calling a .ps1 file inside a Foreach-Object loop.  Have you tried using a custom function instead?
0
 
LVL 18

Expert Comment

by:Raheman M. Abdul
Comment Utility
use this logic instead in your script:
$content = Get-Content $file
$content = $content -replace "t101", "t102"; 
$content = $content -replace "t103", "t102" ;
$content = $content -replace  "t1001", "t2002" 

Open in new window

0
 
LVL 18

Assisted Solution

by:Raheman M. Abdul
Raheman M. Abdul earned 125 total points
Comment Utility
#CRMe.ps1
param( [string] $fileName)

# Check the file exists
if (-not(Test-Path $fileName)) {break}

# Display the original name
"Original filename: $fileName"

$fileObj = get-item $fileName

# Get the Add
$DateStamp = "_cnc3"
$extOnly = $fileObj.extension

if ($extOnly.length -eq 0) {
   $nameOnly = $fileObj.Name
(Get-Content $fileObj.Name) | ForEach-Object { $_ -replace "t101", "t102" ; "t103", "t102" ; "t1001", "t2002" }| Set-Content "$nameOnly-$DateStamp"
}
else {
   $nameOnly = $fileObj.Name.Replace( $fileObj.Extension,'')

$content = Get-Content $fileObj.Name
$content = $content -replace "t101", "t102"; 
$content = $content -replace "t103", "t102" ;
$content = $content -replace  "t1001", "t2002"
$content | Set-Content "$nameOnly$DateStamp$extOnly"
}

Open in new window

I call this script in the folder that I am working in with this script
foreach ($file in get-ChildItem *.txt) { ./CRMe.ps1 $file.name }

write-host "Press any key to continue..."
[void][System.Console]::ReadKey($true)

Open in new window

0
 
LVL 39

Expert Comment

by:footech
Comment Utility
Your syntax as shown above is incorrect.  The -replace operator only takes 3 arguments.
1) the input string
2) the regular expression
3) the replacement string
<string> -replace <regex>[, <replacement>]
The input string is searched for a character (or characters) which matches the regular expression.  The matching characters are then replaced by the replacement string.  The replacement string can be omitted if you just want to remove the matching characters (indicated by the square brackets above).
If you want to perform more than a single replace operation, then you have to specify all the needed elements for each operation.  If the replacement string is the same for multiple operations, some efficiency could be had by if you can form a regular expression that matches multiple patterns.

Keep in mind the text will be replaced exactly as you have it, including case, and by default the -replace operator searches for a case-insensitive match.
(Get-Content $fileObj.Name) | ForEach-Object { ($_ -replace "t10[13]", "t102") -replace "t1001", "t2002" }| Set-Content "$nameOnly-$DateStamp"

Open in new window

0
 

Author Comment

by:bobgraf
Comment Utility
Thanks that's exactly what I was looking for.
0
 
LVL 39

Expert Comment

by:footech
Comment Utility
You realize that the code posted by Raheman includes syntax that doesn't work, and is also quite inefficient in the replace operations that do work?
0
 
LVL 68

Expert Comment

by:Qlemo
Comment Utility
footech is correct, you have ineffectively used the same "replacement" logic at two locations, and only one of them (input file has extension) has been (again ineffectively) handled.
Writing up same logic is something you should avoid as much as possible, because you have to change it more than once if there is the need to expand the script.
#CRMe.ps1
param( [string] $fileName)

# Check the file exists
if (-not(Test-Path $fileName)) {break}

# Display the original name
"Original filename: $fileName"

$fileObj = get-item $fileName

# Get the Add
$DateStamp = "_cnc3"
$extOnly = $fileObj.extension

if ($extOnly.length -eq 0)
  { $target = $fileObj.Name + '-' + $DateStamp }
else
  { $target = $fileObj.BaseName + $DateStamp + $extOnly }

Get-Content $fileObj -replace 't10[13]', 't102' ˋ
                     -replace 't1001'  , 't2002' |
  Set-Content $target

Open in new window

0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:bobgraf
Comment Utility
I appreciate the additional comments. I do understand what you guys are saying. I'm a novice at powershell scripting. I can find scripts on the internet and then adjust them to what I need it to do with some trial and error. Raheman's post did work for what I needed the script to do but Qlemo script is simplified from the original script I was adjusting. I am confused about 2 parts on Qlemo's script. The [13] and the $fileob. Is the $fileob spelling error and supposed to be $fileobj?
There are about 100 find and replace text items in the files. This is for CNC tool grab programming documents that has to be changed for different machines.

if ($extOnly.length -eq 0)
  { $target = $fileObj.Name + '-' + $DateStamp }
else
  { $target = $fileObj.BaseName + $DateStamp + $extOnly }

Get-Content $fileObj -replace 't10[13]', 't102' ˋ
                       $fileOb  -replace 't1001', 't2002' |
  Set-Content $target
0
 
LVL 68

Assisted Solution

by:Qlemo
Qlemo earned 125 total points
Comment Utility
I took the [13] over from footech, as I would have done it the same way probably - it is a regular expression match pattern, telling "either 1 or 3 at this position". So 't10[13]' works for 't101' and 't103',

The $fileob is a copy&waste error, it should not be there at all. Since I'm a Topic Advisor, I took "unfair" advantage and changed my posted code ("usual" members only can edit as long as noone has posted next).

As said, Raheman's code only corrects the part if your file has an extension. The other program branch for files not having an extension is still "broken" (unchanged from your code, and will create a wrong file with unwanted, repeated data).
0
 

Author Comment

by:bobgraf
Comment Utility
Ok, I got what your meaning. I did copy and paste my entries in the section that Raheman's code that was missing to catch files without an extension. I was pretty sure I didn't need that section for what I was using the script for as all the files are .txt files, but I left it in there so I didn't need to adjust the code.

I did not realize that you could do the "it is a regular expression match pattern, telling "either 1 or 3 at this position". So 't10[13]' works for 't101' and 't103'"  That would have cut code in half to 3/4 from my script.

Unfortunately my code is on the production floor adjusting CNC tool grabs so I cannot edit it or I would and test out the new things that are in this post. For the past year they have been manually editing 100's of lines of code in 1000's of CNC programming files at the machine. A couple $6000 tool breaks and the countless hours they were manually adjusting the code they decided to look at something different. Management is very happy with the code so thank you all to have contributed to helping me figure out how to include additional -replace in the script.
0
 
LVL 39

Accepted Solution

by:
footech earned 250 total points
Comment Utility
One syntax correction to avoid confusion.  The following doesn't quite work.
Get-Content $fileObj -replace 't10[13]', 't102' ˋ
                     -replace 't1001'  , 't2002' |
  Set-Content $target

Open in new window


It needs to be either
(Get-Content $fileObj) -replace 't10[13]', 't102' ˋ
                     -replace 't1001'  , 't2002' |
  Set-Content $target

Open in new window

or
Get-Content $fileObj | ForEach { $_ -replace 't10[13]', 't102' ˋ
                     -replace 't1001'  , 't2002' } |
  Set-Content $target

Open in new window


Performance is pretty much identical in my testing.
0
 
LVL 68

Expert Comment

by:Qlemo
Comment Utility
Oops, that is correct.
0
 

Author Comment

by:bobgraf
Comment Utility
Yes, please reopen so I can re-distribute points.
0
 

Author Closing Comment

by:bobgraf
Comment Utility
Thanks for the help. I will be opening up a new question as they want it to skip over files with an _cnc3 in them now.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Utilizing an array to gracefully append to a list of EmailAddresses
A procedure for exporting installed hotfix details of remote computers using powershell
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now