1

I am having below 2 text files with service details in them

File_1

Application Host Helper Service,OS,WARNING
Astro BLSA (Business Logic Server Authentication),OS,CRITICAL
#Base Filtering Engine,OS,WARNING
#Background Tasks Infrastructure Service,OS,WARNING
Cb Defense,OS,WARNING
#Cb Defense WSC,OS,WARNING
Astrogyprocazwatch,OS,WARNING
Astroweberazwatch,OS,WARNING

File_2 (Service List which are having startup type as automatic)

Application Host Helper Service                                  
Astro BLSA (Business Logic Server Authentication)                                                     
Base Filtering Engine                                            
Background Tasks Infrastructure Service
Cb Defense,OS,WARNING   

I want to compare File_2 with File_1. If the entry in File_2 present in File_1 the ignore else put a # in front of the line to comment that. and if it is already commented then it should not get commented again.

The changes should reflect in File_1 itself

Expected Output

Application Host Helper Service,OS,WARNING
Astro BLSA (Business Logic Server Authentication),OS,CRITICAL
#Base Filtering Engine,OS,WARNING
#Background Tasks Infrastructure Service,OS,WARNING
Cb Defense,OS,WARNING
#Cb Defense WSC,OS,WARNING
#Astrogyprocazwatch,OS,WARNING
#Astroweberazwatch,OS,WARNING

Only last 2 entries in File_1 is not present in File_2, so they got commented and rest which are already present/commented will remain as it is.

I was trying the below code, but it is putting # for all the entries and double # for already hashed entries

$File_1 = gc "\\$svr\c$\\Services_20062023.txt"
$GetAutomaticServices = Get-Service | where {$_.StartType -eq "Automatic"} | select DisplayName | Format-Table -HideTableHeaders | out-file "\\$svr\c$\\Automatic_service_list.txt" 
$File_3 = gc "\\$svr\c$\Automatic_service_list.txt" 

foreach($entries in $File_1)
{
    $Final_arr += ($entries -split ',')[-3]
}

$file_2 = $Final_arr | ForEach-Object {
    if ($File_3 -match "$_")
    { "$_" }
    else { "#$_" }
}

Above updated code is working fine but only problem is which are already commented, this code is adding another # in front of it.

Please let me know how do this

  • What have you tried so far? SO isn't a code writing service - no-one is going to take the time to do your job for you, but if you show some effort in solving it yourself, you'll likely get help with specific issues. – boxdog Jul 13 '23 at 08:06
  • @boxdog: I forgot to add the tried code. my mistake – snehasish nandy Jul 13 '23 at 08:06
  • `match` will match *any part* of the input strings(s). You probably want to do: `$File_3 -match "^$_$"` or better: `$File_3 -Contains $_`. As an aside: You didn't initialize the `$Final_arr` array (`$Final_arr = @()`) besides it is better to [avoid using the increase assignment operator (`+=`) to create a collection](https://stackoverflow.com/a/60708579/1701026) – iRon Jul 13 '23 at 09:02
  • So in your code `$File_3` is what you call `File_2` in the explanation above? In which case the content of `Automatic_service_list.txt` will not match your listing for `File_2` ... – Thor Jul 13 '23 at 09:40
  • @Thor: `So in your code $File_3 is what you call File_2` -Yes. If values present in `Automatic_service_list.txt` not available in `$File_1`, we have to comment that entry in `File_1` – snehasish nandy Jul 13 '23 at 10:44
  • @iRon: I tried using your suggestion. `-contain` is commenting all the values. and `match` condition I am currently using is working fine. only problem is I am not able to ignore the lines which are already commented. so the code is adding extra `#` – snehasish nandy Jul 13 '23 at 10:48

2 Answers2

2

There is a pitfall in your question as it contains a lot of trailing spaces in $File2.
Anyways (using the PowerShell when the input is a collection, the operator returns the elements of the collection that match the right-hand value of the expression. If there are no matches in the collection, comparison operators return an empty array feature):

$File1 = @'
Application Host Helper Service,OS,WARNING
Astro BLSA (Business Logic Server Authentication),OS,CRITICAL
#Base Filtering Engine,OS,WARNING
#Background Tasks Infrastructure Service,OS,WARNING
Cb Defense,OS,WARNING
#Cb Defense WSC,OS,WARNING
Astrogyprocazwatch,OS,WARNING
Astroweberazwatch,OS,WARNING
'@ -Split '\r?\n'

$File2 = @'
Application Host Helper Service
Astro BLSA (Business Logic Server Authentication)
Base Filtering Engine
Background Tasks Infrastructure Service
Cb Defense,OS,WARNING
'@ -Split '\r?\n'

$Split2 = $File2.Foreach{ $_.Trim().Split(',', 2)[0] }
$File1 | Foreach-Object {
    if( $_[0] -ne '#' -and -not ($Split2 -eq $_.Trim().Split(',', 2)[0])) {
        "#$_"
    } else {
        $_
    }
}
iRon
  • 20,463
  • 10
  • 53
  • 79
0

I would suggest splitting the service lines inside the ForEach loop, this will make printing the lines much easier.

Now for matching DisplayLine reliably in a multi-line fashion, I think you need to use regular expressions and match the line with anchors (^ and $) to $File_3 with sls (Select-String).

$File_1 = gc services.txt;
$File_3 = gc automatic-services.txt;

$File_1 | % {
  $pattern = [RegEx]::Escape(($_ -split ',')[0]);
  if ( ($_ -match '^#') -or ($File_3 | sls "(?m)^$pattern$") ) { $_ }
  else { "#$_" }
}

Note the (?m) in the regular expression makes the anchors match on line-breaks, see the regular expression quick referense for more details.

Output:

Application Host Helper Service,OS,WARNING
Astro BLSA (Business Logic Server Authentication),OS,CRITICAL
#Base Filtering Engine,OS,WARNING
#Background Tasks Infrastructure Service,OS,WARNING
Cb Defense,OS,WARNING
#Cb Defense WSC,OS,WARNING
#Astrogyprocazwatch,OS,WARNING
#Astroweberazwatch,OS,WARNING
Thor
  • 45,082
  • 11
  • 119
  • 130