Powershell - Pattern Matching - powershell

I have a requirement wherein the log file has some IP address and it needs to be replaced with hostname referring the database. I am getting output with matches for hostname found in database. I am unable to print the IP address for which hostname not found as it is.Can anyone assist in getting the full output.
IP_Address.txt
dhhdhja sasa 10.1.154.6
sasas swssss 10.1.154.10
assas 10.1.154.14
10.1.154.34
10.1.154.38
Hostname.txt
10.1.154.6=>Host1
10.1.154.10=>Host2
10.1.154.14=>Host3
Current Output
dhhdhja sasa 10.1.154.6=>Host1
sasas swssss 10.1.154.10=>Host2
assas 10.1.154.14=>Host3
Expected Output
dhhdhja sasa 10.1.154.6=>Host1
sasas swssss 10.1.154.10=>Host2
assas 10.1.154.14=>Host3
10.1.154.34
10.1.154.38
Code
$log = "C:\Users\IP_Address.txt"
$DB=#()
$DB = Get-Content C:\Users\Hostname.txt
Get-Content $log |
Where-Object {$_ -match '(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'} |
ForEach-Object {
# Try to resolve the IP
Try
{
$IP = $Matches.IP
foreach($DBE in $DB)
{
if($IP -match $DBE.split("=>")[0])
{
$hostname = $DBE
if ($hostname -ne "")
{
Get-Content $log |
Where-Object {$_ -match $IP} |
ForEach-Object {
$_ -replace $IP, $hostname
}
}
}
}
}
catch
{
#$_ -replace $IP, $IP
}
}

Finally I was able to solve it..
Code:
$log = "C:\Users\IP_Address.txt"
$DB=#()
$DB = Get-Content "C:\Users\Hostname.txt"
$file = Get-Content "C:\Users\Hostname.txt"
Get-Content $log |
Where-Object {$_ -match '(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'} |
ForEach-Object {
$IP = $Matches.IP
$containsWord = $file | %{$_ -match $IP}
If($containsWord -contains $true)
{
# Try to resolve the IP
$IP = $Matches.IP
foreach($DBE in $DB)
{
if($IP -match$DBE.split("=>")[0])
{
$hostname = $DBE
if ($hostname -ne "")
{
Get-Content $log |
Where-Object {$_ -match $IP} |
ForEach-Object {
$_ -replace $IP, $hostname
}
}
}
}
}
Else{$_}
}

Try this:
$log = "C:\Users\IP_Address.txt"
$DB=#()
$DB = Get-Content C:\Users\Hostname.txt
## Loop through each line in IP_Address.txt to do the replacement, as needed
Get-Content $log | ForEach-Object {
## Perform work if we run into a line with an IP
if ($_ -match '(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') {
$DBE = $DB | ? { $_ -like "$($_)*" }
## Make sure the entry we get back is a valid IP
if ($DBE -match '(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') {
$_.Replace($_, $DBE) ## Replace just the IP with the IP/hostname from hostname.txt
} else {
$_ ## Else just emit the line as-is which still contains the original IP
}
} else {
$_
}
}

Related

How to read a specific item of INI file using PowerShell?

I want to read a specific item of my INI file, I have 5 Items in the section of my INI file, and I want to read 4 items, except items number 3.
I already tried to read all the items, but I can not find a way how to specify the item that I want to read and the format of the file that I read is like this:
Name Value
AA 12
BB 13
CC 14
DD 15
EE 16
I used this command to execute it.
File1.ps1 Read-File -FilePath C:\Users\Data.ini -a_section Code -store C:\Users\
function Read-File {
Param(
[Parameter(Mandatory=$true)]$FilePath,
[Parameter(Mandatory=$true)]$a_section,
[Parameter(Mandatory=$true)]$store
)
$input_file = $FilePath
$ini_file = #{}
Get-Content $input_file | ForEach-Object {
$_.Trim()
} | Where-Object {
$_ -notmatch '^(;|$)'
} | ForEach-Object {
if ($_ -match '^\[.*\]$') {
$section = $_ -replace '\[|\]'
$ini_file[$section] = #{}
} else {
$key, $value = $_ -split '\s*=\s*', 2
$ini_file[$section][$key] = $value
}
}
$Path_Store = $store
$Get_Reg = $ini_file.($a_section)
$Output = $Get_Reg | Out-File $Path_Store\Out_Test
}
$cmd, $params = $args
& $cmd #params
My expectation result, I have an output file like this
AA=12
BB=13
DD=15
EE=16
My INI File look like this:
[Name]
1=Joe
2=Grace
[Code]
AA=12
BB=13
CC=14
DD=15
EE=16
Try this:
function Get-IniSection {
Param(
[Parameter(Mandatory=$true)]$Path,
[Parameter(Mandatory=$true)]$SectionName
)
$ini_file = #{}
Get-Content $Path | ForEach-Object {
$_.Trim()
} | Where-Object {
$_ -notmatch '^(;|$)'
} | ForEach-Object {
if ($_ -match '^\[.*\]$') {
$section = $_ -replace '\[|\]'
$ini_file += #{ $section = #{} }
} else {
$key, $value = $_ -split '\s*=\s*', 2
$ini_file[$section] += #{ $key = $value }
}
}
return $ini_file[$SectionName]
}
$section = Get-IniSection -Path "C:\temp\test.ini" -SectionName "code"
$section.GetEnumerator() | Where-Object { $_.Name -ne "EE" }
$section.GetEnumerator() | ForEach-Object { "$($_.Name)=$($_.Value)" }
$section.GetEnumerator() |
Where-Object { $_.Name -in #("A1","AE","AP","AS","E1","E2","JP","M1","M2","N1","N2","P1","P2","P3","P4","PR","RU","S1","S2","W1","W2","W3","W4","ZH") } |
Select-Object -ExpandProperty "Value"
$section.GetEnumerator() |
Where-Object { $_.Name -in #("A1","AE","AP","AS","E1","E2","JP","M1","M2","N1","N2","P1","P2","P3","P4","PR","RU","S1","S2","W1","W2","W3","W4","ZH") } |
Foreach-Object { ($_.Value -split ",")[0] }

Removing extra blank space from PowerShell output

I have a PowerShell program to replace some strings with another from an input file but the output file has an extra space/line when compared to input file.
$InputACKFile = 'C:\Testing_Newline\Aj*.dat'
Write-Host "Found " ($InputACKFile | Measure-Object).Count " files to process"
$InputACKFile = Get-ChildItem $InputACKFile
foreach ($xfile in $InputACKFile) {
Write-Host "Processing file: $xFile`r"
#((Get-Content $xfile).Replace("~", "`n")) | Out-File $xfile.FullName
[System.IO.File]::ReadAllText($xfile).Replace("~","`n") |
Set-Content $xfile
$flag = 0
(Get-Content $xfile | ForEach {
if ($_ -match "^PQ\*") {
$_ -replace "test1", "test2"
} elseif ($_ -match "^TA\*") {
$_ -replace "test1", "test2"
} elseif ($_ -match "^ABC\*RS\*") {
$_ = '';
$flag = 1
} elseif ($_ -match "^(DE\*)([0-9]+)(\*[0-9]+)$" -and $flag -eq 1) {
$_ -replace ($matches[2]), ([int]::Parse($matches[2])-1);
$flag = 0
} else{
$_
}
}) | Out-File $xfile.FullName -Encoding Ascii
((Get-Content $xfile) -join("~")) | Set-Content $xfile.FullName
}

Find and Replace multi-line string

I'm trying to find a string and add the string needed for a program.
I need the code to look to see if the action = run fast already exists and if so do nothing.
$Input = GetContent "${Env:ProgramFiles}\myprogram\file.conf"
$replace = #"
[MyAction_Log]
action = run fast
"#
$Input -replace ('action = run fast') -replace ('\[MyAction_Log\]',$replace) | set-content "${Env:ProgramFiles}\myprogram\file.conf"
I would check before wantonly replacing things you think exist. Also, never use $Input as a variable name; it's an automatic variable and won't do what you think it will (treat it as read-only).
$path = "$Env:ProgramFiles\prog\file.conf"
$file = Get-Content -Path $path
$replacementString = #'
[MyAction_Log]
action = run fast
'#
if ($file -notmatch 'action\s=\srun\sfast')
{
$file -replace '\[MyAction_Log\]', $replacementString |
Set-Content -Path $path
}
An alternative that's able to cope with the action key being located anywhere in the [MyAction_Log] section
$Inside = $False
$Modified = $False
$Path = "$( $env:ProgramFiles )\prog\file.conf"
$NewLines = Get-Content $Path |
ForEach-Object {
if( $_.Trim() -like "[*]" ) { $Inside = $False }
if( $_.Trim() -like "*[MyAction_Log]*" ) { $Inside = $True }
If( $Inside -and $_ -like "action = *" -and $_ -notlike "*run fast*" ) { $Modified = $True; "action = run fast" } else { $_ }
}
If( $Modified ) { $NewLines | Set-Content $Path }

parsing script never ends

i have the following script but it does never end executing.
what could be the issue ? I tried to debug it but apparently it works correctly with a single file, but when I throw it against a folder full of content fails.
$path = split-path -parent $MyInvocation.MyCommand.Definition
$files = Get-ChildItem "$path\CodeForCertification\5_SourceCode\*" -Include *.c,*.h -Recurse | where{
! $_.PSIsContainer
}#$PSScriptRoot
ForEach ($file in $files){
$data = Get-Content -Path $file.FullName
$feature = Get-Content "$path\Disabled_Features.txt"
#[System.ArrayList]$Modifier
$nl=[Environment]::NewLine
$Modifier=#()
$flag=0
$data = $data | ForEach-Object -Begin {
$ignore = $false; $levels = 0
} -Process {
for($counter=0; $counter -lt $feature.Count; $counter++){
$parse = $feature[$counter]
if($_ -match "^#ifdef $parse" -And $flag -eq '0') {
$ignore = $true
$flag = 1;
}
}
if($ignore) {
if ($_ -match "^#ifdef") {
$levels++
}elseif ($_ -match "#endif") {
if($levels -ge 1) {
$levels--
if($levels -eq '0'){
$ignore = $false
}
}
}
}else {
$flag=0
$temp=$_
$_
$Modifier+="$temp"
}
}
$data | Out-File $file.FullName
}
OK, Jackson, let's solve your problem before you enter some kind of question spam filter ;-)
Consider this (just put it somewhere at the start of your script):
function RemoveUndesiredFeatures([string[]]$lines,[string[]]$undesiredFeatures)
{
$inIgnoreBlock = $false
$nestingLevel = 0
foreach ($line in $lines)
{
if ($inIgnoreBlock)
{
# Only search for nested blocks and end of block
if ($line -like "#ifdef*")
{
$nestingLevel++
}
elseif ($line -like "#endif*")
{
$nestingLevel--
}
if ($nestingLevel -eq 0)
{
$inIgnoreBlock = $false
}
}
else
{
# Search for undesired feature
$isIfdefMatch = $line -match "#ifdef (?<feature>\w+)"
if ($isIfdefMatch -and ($Matches.feature -in $undesiredFeatures))
{
# Ignore Feature
$inIgnoreBlock = $true
$nestingLevel++
}
else
{
# Output line
$line
}
}
}
}
Here is my example to use it:
$undesiredFeatures = #("F1","F2") # Just as example. Get-Content on a file with features is also fine
$files = Get-ChildItem *.c,*.h -Recurse # Again, just as example
foreach ($file in $files)
{
$lines = Get-Content $file.FullName
$changedLines = RemoveUndesiredFeatures $lines $undesiredFeatures
if ($changedLines.Count -ne $lines.Count)
{
# Features were removed. Write out changed file (to a different file to preserve my test files)
Set-Content -Value $changedLines -Path "$($file.FullName).changed"
}
}

Add Content in Powershell

I need to search through multiple files and underneath specific lines i need to insert lines referenced previously in each respective file. So far i cannot get my script to work at all.
This is what i have so far :
$TextLocation = "M:\test"
$files = get-childitem -filter *.gto -path $TextLocation
Foreach ($file in $files) {
$pagetitle = "DS_PGSEQ-DC:"
$a = Get-Content $file.FullName | Select-String "AssignedToUserID-TZ"
$b = Get-Content $file.FullName | Select-String "EFormID-TZ"
Foreach ($line in $file)
{
if([String]$line -eq "DS_PGSEQ-DC:0001")
{
}
elseif([String]$line -eq $pagetitle)
{
Add-Content $file.FullName ($a -and $b)
}
}
}
There are two common ways for inserting text into a text file:
Process the input file(s) line-by-line, write the output to a temporary file and replace the input file(s) with them temp file afterwards.
for ($file in $files) {
$filename = $file.FullName
Get-Content $filename | % {
if ( $_ -match 'seach pattern' ) {
$_
"new line"
}
} | Out-File $tempfile
MoveItem $tempfile $filename -Force
}
Read the entire content of the file(s), insert the text by using a regular expression replacement, and write the modified content back to the file(s).
for ($file in $files) {
$text = [System.IO.File]::ReadAllText($file.FullName)
$text -replace '.*search pattern.*', "`$0`nnew line" |
Out-File $file.FullName
}
$TextLocation = "M:\test"
$Outputlocation = "M:\test\output"
$files = get-childitem -filter *.gto -path $TextLocation
Foreach ($file in $files) {
$pattern = "\d\d\d[2-9]"
$found=$false
$contains=$false
$lines = Get-Content($file.FullName) |
Foreach-object {
if ($_ -match "AssignedToUserID-TZ") {
$a = $_
}
if ($_ -match "EFormID-TZ") {
$b = $_
}
if ($_ -match "DS_PGSEQ-DC:$pattern") {
if($found -eq $false) {
$found=$true
}
} else {
$found=$false
}
if ($found -eq $true) {
$contains=$true
#Add Lines after the selected pattern
$_
$a
$b
}
if ($found -ne $true) {
$_
}
} | Set-Content($Outputlocation + "\" + $file.Name)
}