Need to compare only specific lines

Copper Contributor

Hi, Can someone help to write a script to compare only few required lines between configuration files. For example if file1 has key value pair stating abc=123, it should compare with another file file2 and show the result if there is any changes in that specified line.

 

In my configuration file there will hundreds of lines. So those lines should be memorized first for easy comparing.

12 Replies
Could you share a part of the configuration file if possible and what do you have so far as a script?

Hi @Harm_Veenstra,

 

Sure. Below is the part of the script. Script need to identify only the lines which doesn't have '#' and highlighted in red color (there is no color code in original file. Highlighted by me for easy identification)

 

# This parameter defines whether to use CORS filter on Auth server security filter chain.
# This parameter can only be set during initialization.
#
# Default=true
#
# auth.enable.corsfilter=true
auth.enable.corsfilter=true

# This parameter defines the number of days that a user can keep a password before it is expired
# This parameter can only be set during initialization.
#
# Default=60
#
# auth.password.expiration.days=60
auth.password.expiration.days=60

# This parameter defines the number of previous passwords that cannot be used for a new password.
# This parameter can only be set during initialization.
#
# Default=1
#
# auth.password.history.size=1
auth.password.history.size=1
 
 

 

@VinayNaguru I made a very simple compare 

 

$file1 = get-content .\file1.txt
$file2 = get-content .\file2.txt
$contentsfile1 = @()

foreach ($line in $file1) {
    if ($line.StartsWith('#')) {
        #Skip
    }
    else {
        if ($line.Contains('=')) {
            $contentsfile1 += $line
        }
    }
}

foreach ($value in $contentsfile1) {
    if (-not ($file2 | Select-String $value)) {
        $found = $file2 | Select-String $value.Split('=')[0] | Select-String -Pattern '#' -NotMatch
        write-host ("{0} not found, value found is {1}" -f $value, $found) -ForegroundColor Red
    
    }
}

 

Contents file 1

# This parameter defines whether to use CORS filter on Auth server security filter chain.
# This parameter can only be set during initialization.
#
# Default=true
#
# auth.enable.corsfilter=true
auth.enable.corsfilter=false

# This parameter defines the number of days that a user can keep a password before it is expired
# This parameter can only be set during initialization.
#
# Default=60
#
# auth.password.expiration.days=60
auth.password.expiration.days=30

# This parameter defines the number of previous passwords that cannot be used for a new password.
# This parameter can only be set during initialization.
#
# Default=1
#
# auth.password.history.size=1
auth.password.history.size=2

Contents File 2

# This parameter defines whether to use CORS filter on Auth server security filter chain.
# This parameter can only be set during initialization.
#
# Default=true
#
# auth.enable.corsfilter=true
auth.enable.corsfilter=true

# This parameter defines the number of days that a user can keep a password before it is expired
# This parameter can only be set during initialization.
#
# Default=60
#
# auth.password.expiration.days=60
auth.password.expiration.days=60

# This parameter defines the number of previous passwords that cannot be used for a new password.
# This parameter can only be set during initialization.
#
# Default=1
#
# auth.password.history.size=1
auth.password.history.size=1

 

Output on screen:
auth.enable.corsfilter=false not found, value found is auth.enable.corsfilter=true
auth.password.expiration.days=30 not found, value found is auth.password.expiration.days=60
auth.password.history.size=2 not found, value found is auth.password.history.size=1

 

@VinayNaguru  @Harm_Veenstra 

 

I went for something a little more complex. May be overkill for this scenario but here it is anyway.

 

function Get-FileDifferences([string]$SourceFile, [string]$TargetFile)
{
    if ((Test-Path -Path $SourceFile) -and (Test-Path -Path $TargetFile))
    {
        $TargetHashes = [System.Collections.Generic.Dictionary[[int], [string]]]::new();

        # Read the target file first.
        Get-Content -Path $TargetFile |
            ForEach-Object {
                if (-not [string]::IsNullOrWhiteSpace($_) -and -not $_.Replace(" ", "").StartsWith("#") -and -not $TargetHashes.ContainsKey(($Hash = $_.GetHashCode())))
                {
                    $null = $TargetHashes.Add($Hash, $_);
                }
            }

        # Read the source file and prune matching items as we go, while reporting any differences.
        Get-Content -Path $SourceFile |
            ForEach-Object {
                if (-not [string]::IsNullOrWhiteSpace($_) -and -not $_.Replace(" ", "").StartsWith("#"))
                {
                    if ($TargetHashes.ContainsKey(($Hash = $_.GetHashCode())))
                    {
                        $null = $TargetHashes.Remove($Hash);
                    }
                    else
                    {
                        [PSCustomObject] @{
                            File = "Source";
                            Variation = $_;
                        }
                    }
                }
            }

        # List anything remaining in $TargetHashes as these are implicitly the differences.
        if ($TargetHashes.Count -gt 0)
        {
            foreach ($Entry in $TargetHashes.GetEnumerator())
            {
                [PSCustomObject] @{
                    File = "Target";
                    Variation = $Entry.Value;
                }
            }
        }
    }
    else
    {
        throw "One or both files were not found.";
    }
}

 

With the output looking like:

 

LainRobertson_0-1662627970154.png

 

I simply used directory listing for the two source files but it doesn't matter what format they are - so long as they're text and not binary.

 

Cheers,

Lain

Hi @Harm_Veenstra,

 

Wow. Let me try the scenario. Thank you so much for help me.

Hi Lain. Wow. I will try your script too. Thank you for help me and making my work easier.
Let us know the results :)
It worked for text and config files. But not working for the Yaml file. So it will be different for it?
Those are differently formatted, there are online compare tools for that and Linux Dyff tools... Didn't see a windows version of that

@VinayNaguru 

 

The example function I provided seems to handle YAML just fine.

 

YAML file 1

{
  "PreviewRun": true,
  "YamlOverride": "
# your new YAML here, optionally
"
}

 

YAML file 2

{
  "PreviewRun": false,
  "YamlOverride": "
# your new YAML here, optionally
"
}

 

Function output

LainRobertson_0-1662860183449.png

 

Cheers,

Lain

 

Did you used to write .net code?
yeah the idea is that we can use this code to iterate against all the customer configuration files