I'm pretty new to powershell/programming so bear with me. I have this bug that appends the new renamed path to a new-line without the rest of path.
The console output:
/content/pizza/en/ingredients/
helloworld/menu-eng.html
What I want:
/content/pizza/en/ingredients/helloworld/menu-eng.html
What the code below is supposed to do is rename a bunch paths. Right now testName is hard-coded but after I get this to work properly it will be dynamic.
My code:
$testName = "helloworld"
$text = (Get-Content W:\test\Rename\rename.csv) | Out-String
$listOfUri = Import-Csv W:\test\Rename\rename.csv
foreach ($element in $listOfUri) {
if ($element -match "menu-eng.html") {
$elementString = $element.'ColumnTitle' | Out-String
$elementString = $elementString.Replace('menu-eng.html', '')
$varPath1 = $elementString
$elementString = $elementString.Insert('', 'http://www.pizza.com')
$elementName = ([System.Uri]$elementString).Segments[-1]
$elementString = $elementString.Replace($elementName, '')
$elementString = $elementString.Replace('http://www.pizza.com', '')
$varPath2 = $elementString.Insert($elementString.Length, $testName + '/')
$text = $text.Replace($varPath1.Trim(), $varPath2)
}
}
$text
Assuming your .csv file looks like this:
ColumnTitle,Idk
/content/pizza/en/ingredients/SPAM/menu-eng.html,Stuff
Then:
$testName = 'helloworld'
foreach ($row in Import-CSV d:\rename.csv) {
$bit = $row.'ColumnTitle'.Split('/')[-2]
$row.'ColumnTitle'.replace($bit, $testName)
}
I have no real idea what all the rest of your code is for, particularly my earlier comment, your line:
$text = (Get-Content W:\test\Rename\rename.csv) | Out-String
is making $text into an /array/ of all the lines in the file, including the headers. You can still use .Replace() on it in PowerShell, but it's going to do the replace on every line. I can't quite see how that gives you the output you get, but it will give you multiple lines for every line in the input file.
Related
I'm trying to insert my CSV into my SQL Server database but just wondering how can I subtract the last three character from CSV GID column and then assigned it to my $CSVHold1 variable.
My CSV file look like this
GID Source Type Message Time
KLEMOE http://google.com Od Hello 12/22/2022
EEINGJ http://facebook.com Od hey 12/22/2022
Basically I'm trying to get only the first three character from GID and pass that value to my $CSVHold1 variable.
$CSVImport = Import-CSV $Global:ErrorReport
ForEach ($CSVLine1 in $CSVImport) {
$CSVHold1 = $CSVLine1.GID | ForEach-Object { $_.$GID = $_.$GID.subString(0, $_.$GID.Length - 3); $_ }
$CSVGID1 = $CSVLine1.GID
$CSVSource1 = $CSVLine1.Source
$CSVTYPE1 = $CSVLine1.TYPE
$CSVMessage1 = $CSVLine1.Message
}
I'm trying to do like above but some reason I'm getting an error.
You cannot call a method on a null-valued expression.
Your original line 3 was/is not valid syntax as Santiago pointed out.
$CSVHold1 = $CSVLine1.GID | ForEach-Object { $_.$GID = $_.$GID.subString(0, $_.$GID.Length - 3); $_ }
You are calling $_.$GID but you're wanting $_.GID
You also don't need to pipe the object into a loop to achieve what it seems you are asking.
#!/usr/bin/env powershell
$csvimport = Import-Csv -Path $env:HOMEDRIVE\Powershell\TestCSVs\test1.csv
##$CSVImport = Import-CSV $Global:ErrorReport
ForEach ($CSVLine1 in $CSVImport) {
$CSVHold1 = $CSVLine1.GID.SubString(0, $CSVLine1.GID.Length - 3)
$CSVGID1 = $CSVLine1.GID
$CSVSource1 = $CSVLine1.Source
$CSVTYPE1 = $CSVLine1.TYPE
$CSVMessage1 = $CSVLine1.Message
Write-Output -InputObject ('Changing {0} to {1}' -f $CSVLine1.gid, $CSVHold1)
}
Using your sample data, the above outputs:
C:> . 'C:\Powershell\Scripts\dchero.ps1'
Changing KLEMOE to KLE
Changing EEINGJ to EEI
Lastly, be aware that that the SubString method will fail if the length of $CSVLine1.GID is less than 3.
this is probably really simple... but how do I check which lines of a log/config file contain any of the strings from a string array?
Example of file (I want lines 3 and 5)
[Privilege Rights]
SeSystemtimePrivilege = *S-1-5-19,*S-1-5-21-2262136377-125853592-2400401627-1119,*S-1-5-32-544
SeDenyNetworkLogonRight = Guest
SeCreatePagefilePrivilege = *S-1-5-32-544
SeDenyServiceLogonRight = *S-1-5-21-2262136377-125853592-2400401627-1119
SeRemoteShutdownPrivilege = *S-1-5-32-544
SeAuditPrivilege = *S-1-5-19,*S-1-5-20
Script I am using:
$SeRightsArray = #(
'SeDenyNetworkLogonRight',
'SeDenyBatchLogonRight',
'SeDenyServiceLogonRight',
'SeDenyInteractiveLogonRight',
'SeDenyRemoteInteractiveLogonRight')
$LocalPolicyExport = gc "C:\local-security-policy.inf"
Foreach($Line in $LocalPolicyExport){
if ($Line -match $SeRightsArray ){
write-host "FOUND - $line"
}
}
Normally I would use something like -contains or -in, but that doesn't work
You can use gc "C:\local-security-policy.inf" | select-string $seRightsArray. No need for a loop
PS C:\> gc .\test.txt|select-string $SeRightsArray
SeDenyNetworkLogonRight = Guest
SeDenyServiceLogonRight = *S-1-5-21-2262136377-125853592-2400401627-1119
I have a requirement, in which I need to do read line by line, and then do string/character replacement in a datafile having data in windows latin 1.
I've written this powershell (my first one) initially using out-file -encoding option. However the output file thus created was doing some character translation. Then I searched and came across WriteAllLines, but I'm unable to use it in my code.
$encoding =[Text.Encoding]::GetEncoding('iso-8859-1')
$pdsname="ABCD.XYZ.PQRST"
$datafile="ABCD.SCHEMA.TABLE.DAT"
Get-Content ABCD.SCHEMA.TABLE.DAT | ForEach-Object {
$matches = [regex]::Match($_,'ABCD')
$string_to_be_replaced=$_.substring($matches.Index,$pdsname.Length+10)
$string_to_be_replaced="`"$string_to_be_replaced`""
$member = [regex]::match($_,"`"$pdsname\(([^\)]+)\)`"").Groups[1].Value
$_ -replace $([regex]::Escape($string_to_be_replaced)),$member
} | [System.IO.File]::WriteAllLines("C:\Users\USer01", "ABCD.SCHEMA.TABLE.NEW.DAT", $encoding)
With the help of an answer from #Gzeh Niert, I updated my above script. However, when I execute the script the output file being generated by the script has just the last record, as it was unable to append, and it did an overwrite, I tried using System.IO.File]::AppendAllText, but this strangely creates a larger file, and has only the last record. In short its likely that empty lines are being written.
param(
[String]$datafile
)
$pdsname="ABCD.XYZ.PQRST"
$encoding =[Text.Encoding]::GetEncoding('iso-8859-1')
$datafile = "ABCD.SCHEMA.TABLE.DAT"
$datafile2="ABCD.SCHEMA.TABLE.NEW.DAT"
Get-Content $datafile | ForEach-Object {
$matches = [regex]::Match($_,'ABCD')
if($matches.Success) {
$string_to_be_replaced=$_.substring($matches.Index,$pdsname.Length+10)
$string_to_be_replaced="`"$string_to_be_replaced`""
$member = [regex]::match($_,"`"$pdsname\(([^\)]+)\)`"").Groups[1].Value
$replacedContent = $_ -replace $([regex]::Escape($string_to_be_replaced)),$member
[System.IO.File]::AppendAllText($datafile2, $replacedContent, $encoding)
}
else {
[System.IO.File]::AppendAllText($datafile2, $_, $encoding)
}
#[System.IO.File]::WriteAllLines($datafile2, $replacedContent, $encoding)
}
Please help me figure out where I am going wrong.
System.IO.File.WriteAllLines is getting either an array of strings or an IEnumerable of strings as second parameter and cannot be piped to a command because it is not a CmdLet handling pipeline input but a .NET Framework method.
You should try storing your replaced content into a string[]to use it as parameter when saving the file.
param(
[String]$file
)
$encoding =[Text.Encoding]::GetEncoding('iso-8859-1')
$replacedContent = [string[]]#(Get-Content $file | ForEach-Object {
# Do stuff
})
[System.IO.File]::WriteAllLines($file, $replacedContent, $encoding)
I have a large CSV file in which some fields have a new line embedded. Excel 2016 produces errors when importing a CSV with rows which have fields with a new line embedded.
Based on this post, I wrote code to replace any new line in any field with a space. Below is a code block that duplicates the functionality and issue. Option 1 works. Option 2, which is commented out, casts my object to a string. I was hoping Option 2 might run faster.
Question: Is there a better way to do this to optimize for performance processing very large files?
$array = #([PSCustomObject]#{"ID"="1"; "Name"="Joe`nSmith"},
[PSCustomObject]#{"ID"="2"; "Name"="Jasmine Baker"})
$array = $array | ForEach-Object {
#Option 1: produces an Object, but is code optimized?
foreach ($n in $_.PSObject.Properties.Name) {
$_.PSObject.Properties[$n].Value = `
$_.PSObject.Properties[$n].Value -replace "`n"," "
}
#Option 2: produces a string, not an object
#$_ = $_ -replace "`n"," "
$_
}
Keep in mind that in my real-world use case, each row has > 15 fields and any combination of them may have one or more new lines embedded.
Use the fast TextFieldParser to read, process, and build the CSV from the file (PowerShell 3+):
[Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') >$null
$parser = New-Object Microsoft.VisualBasic.FileIO.TextFieldParser 'r:\1.csv'
$parser.SetDelimiters(',')
$header = $parser.ReadFields()
$CSV = while (!$parser.EndOfData) {
$i = 0
$row = [ordered]#{}
foreach ($field in $parser.ReadFields()) {
$row[$header[$i++]] = $field.replace("`n", ' ')
}
[PSCustomObject]$row
}
Or modify each field in-place in an already existing CSV array:
foreach ($row in $CSV) {
foreach ($field in $row.PSObject.Properties) {
$field.value = $field.value.replace("`n", ' ')
}
}
Notes:
foreach statement is much faster than piping to ForEach-Object (also aliased as foreach)
$stringVariable.replace() is faster then -replace operator
I have a few URLs which would need to cut and separate the first part of the each URL, i.e example1.com, example2.com, example3.com from each line and store in a variable
Contents in url.csv
https://example1.com/v1/test/f3de-a8c6-464f-8166-9fd4
https://example2.com/v1/test/14nf-d7jc-54lf-fd90-fds8
https://example3.com/v1/test/bd38-17gd-2h65-0j3b-4jf6
Script:
$oldurl = Import-CSV "url.csv"
$newurl = $oldurl.list -replace "https://"
This would replace https://, however the rest of each cannot be hard coded as those values can change.
What could be change code change required to cut anything from and after /v1/ along with https://?
$list = #(
"https://example1.com/v1/test/f3de-a8c6-464f-8166-9fd4",
"https://example2.com/v1/test/14nf-d7jc-54lf-fd90-fds8",
"https://example3.com/v1/test/bd38-17gd-2h65-0j3b-4jf6"
)
$result = $list | %{
$uri = [System.Uri] $_
$uri.Authority
}
$result
See System.Uri properties to potentially assemble the information you need in your result list.
This will cut off anything after "/v1/" and it self. Is that what you want?
$string = "https://example1.com/v1/test/f3de-a8c6-464f-8166-9fd4"
$string = $string -replace "https://"
$pos = $string.IndexOf("/v1/")
$result = $string.Substring(0, $pos)
$result
Output: example1.com