Reputation: 1911
I am doing classic find&replace in some .txt file with powershell. How can I "save" file at the end? I tried with | Set-Content but nothing happens. Maybe I need to Add-Content first?
#Find what?
$optionBuilderStringToFind = "optionsBuilder.UseSqlServer"
$findUsingKeywordString = "using Microsoft."
#Replace with
$namespaceAdd = "using Microsoft.Extensions.Configuration;"
$optionBuilderConfigurable ="optionsBuilder.UseSqlServer(_configuration.GetConnectionString(`"Database`")
);"
gc -Path .\APSContext.cs | % {
if ($_ -match "using System;") {
$_ = $_ + "`n" + $namespaceAdd
#write-host $_
}
if ($_ -match "optionsBuilder.UseSqlServer") {
$_ = $optionBuilderConfigurable
#write-host $_
}
} | Set-Content -Path .\test.cs
Update: Here is testFile where I am looking to alter it. The content of the file is not important. I want to add another reference like "using Something.Something" and in the middle of the file to replace "optionsBuilder.UseSqlServer("dfjidfjljfiejf88");"
with "optionsBuilder.UseSqlServer("_configtest");"
:
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace SRC.APS.Model.APSDB
{
public partial class APSContext : DbContext
{
public APSContext()
{
}
public APSContext(DbContextOptions<APSContext> options)
: base(options)
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("dfjidfjljfiejf88");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
}
Maybe I need to use Out-String instead?
Upvotes: 0
Views: 57
Reputation: 338316
Any script block in Powershell can produce values. This is done by not storing a value in a variable:
{ $foo = 3 }
produces nothing{ 3 }
produces the integer 3
.In the same way
ForEach-Object { $_ = "something" }
produces nothingForEach-Object { $_ = "something"; $_ }
produces the string "something"
Your loop body does not output anything, it's like the upper example above. Therefore, Set-Content
has nothing to do. Modify the block to actually return the changed value of $_
:
$replacements = @(
@{regex='using (System|Potentially|Others);'; replacement='using Microsoft.$1;' }
@{regex='optionsBuilder\.UseSqlServer\("[^"]*"\)'; replacement='optionsBuilder.UseSqlServer("Database")' }
# more search/replace pairs
)
Get-Content .\APSContext.cs -Encoding UTF8 | ForEach-Object {
foreach ($item in $replacements) {
$_ = $_ -replace $item.regex, $item.replacement
}
$_ # <--- this is what produces the line
} | Set-Content -Path .\test.cs -Encoding UTF8
That being said, never load or save text files without specifying their encoding. For C# source code files, I think UTF-8 is the default.
And that being said, modifying source code with regular expressions is not a good thing to do. If this is a one-off, fine. If you plan to do this on a regular basis, you are doing something wrong. Work with configuration files or environment variables instead of keeping in your codebase literal values that are subject to regular change.
Upvotes: 1
Reputation: 7489
as i mentioned - and as Tomalak pointed out - your mucking with the current pipeline object is the source of the glitch. [grin] this code fixes a logic error in your IF cascade [which may be better done with a switch
block], removes the unwise $_
fiddling, and then ensures there is always some output.
# fake reading in a text file
# in real life, use Get-Content
$InStuff = @'
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace SRC.APS.Model.APSDB
{
public partial class APSContext : DbContext
{
public APSContext()
{
}
public APSContext(DbContextOptions<APSContext> options)
: base(options)
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("dfjidfjljfiejf88");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
}
'@ -split [environment]::NewLine
#Find what?
$optionBuilderStringToFind = "optionsBuilder.UseSqlServer"
$findUsingKeywordString = "using Microsoft."
#Replace with
$namespaceAdd = 'using Microsoft.Extensions.Configuration;'
$optionBuilderConfigurable ='optionsBuilder.UseSqlServer(_configuration.GetConnectionString("Database"));'
$InStuff | ForEach-Object {
if ($_ -match "using System;")
{
$_ + "`n" + $namespaceAdd
#write-host $_
}
elseif ($_ -match "optionsBuilder.UseSqlServer")
{
$optionBuilderConfigurable
#write-host $_
}
else
{
$_
}
}
output ...
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace SRC.APS.Model.APSDB
{
public partial class APSContext : DbContext
{
public APSContext()
{
}
public APSContext(DbContextOptions<APSContext> options)
: base(options)
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(_configuration.GetConnectionString("Database"));
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
}
Upvotes: 0