Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Can't get Powershell Script to work

Posted on 2016-10-31
16
Medium Priority
?
163 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 3
  • +2
16 Comments
 
LVL 16

Expert Comment

by:Jason Crawford
ID: 41867440
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 19

Expert Comment

by:Raheman M. Abdul
ID: 41867462
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 19

Assisted Solution

by:Raheman M. Abdul
Raheman M. Abdul earned 500 total points
ID: 41867469
#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
Looking for the Wi-Fi vendor that's right for you?

We know how difficult it can be to evaluate Wi-Fi vendors, so we created this helpful Wi-Fi Buyer's Guide to help you find the Wi-Fi vendor that's right for your business! Download the guide and get started on our checklist today!

 
LVL 41

Expert Comment

by:footech
ID: 41867479
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
ID: 41867494
Thanks that's exactly what I was looking for.
0
 
LVL 41

Expert Comment

by:footech
ID: 41867503
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 71

Expert Comment

by:Qlemo
ID: 41868123
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
 

Author Comment

by:bobgraf
ID: 41868407
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 71

Assisted Solution

by:Qlemo
Qlemo earned 500 total points
ID: 41868533
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
ID: 41868558
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 41

Accepted Solution

by:
footech earned 1000 total points
ID: 41868971
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 71

Expert Comment

by:Qlemo
ID: 41869012
Oops, that is correct.
0
 

Author Comment

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

Author Closing Comment

by:bobgraf
ID: 41869084
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

Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this post we will be converting StringData saved within a text file into a hash table. This can be further used in a PowerShell script for replacing settings that are dynamic in nature from environment to environment.
There are times when we need to generate a report on the inbox rules, where users have set up forwarding externally in their mailbox. In this article, I will be sharing a script I wrote to generate the report in CSV format.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…

636 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