Solved

Can't get Powershell Script to work

Posted on 2016-10-31
16
138 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 15

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 125 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 40

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 40

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 69

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 69

Assisted Solution

by:Qlemo
Qlemo earned 125 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 40

Accepted Solution

by:
footech earned 250 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 69

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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Set OWA language and time zone in Exchange for individuals, all users or per database.
A procedure for exporting installed hotfix details of remote computers using powershell
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…
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…

730 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