Al James
Al James

Reputation: 13

Powershell foreach loop reading csv, manipulating and writing out to txt

EDIT: Answered by @Theo

Thanks Theo, works perfectly against the 1000+ line input file. I'll be checking all those commands with Google so I can start to understand what you did / how you did it, but it's all good and thanks again!

:EDIT

Sorry for any formatting errors, this is my first question here.

I am trying to write a script for Fortigate Firewall by using Powershell to read in from a csv (or txt) file of URLs to block.

Current code I've worked out for myself with much help from various posts here on Stack Overflow, sample input, expected output and actual output.

In the sections below labelled: This is what I want the output to be

and

This is the output I get in the txt file

There are line spaces that should not be there, but I can't get the formatting right and if I remove the lines to post, it gives me a single line with everything jumbled up.

Can anybody tell me where I'm going wrong with the code?

Many thanks in advance, Al

I have the following code so far:

$fileout = "C:\ScriptTests\testcli.txt"

if (Test-Path $fileout) {
  Remove-Item $fileout
}

Add-Content -Path $fileout -Value "config webfilter urlfilter"
Add-Content -Path $fileout -Value "edit 1"
$nameset = "set name " + '"Test URL-Block"'
Add-Content -Path $fileout -Value $nameset
Add-Content -Path $fileout -Value "config entries"

$filein = "C:\ScriptTests\testblock.csv"
$counter1 = 1

Get-Content $filein

$contentout = 
    ForEach($fline in $filein)
    {
    $editnum = 'edit' + $counter1
    $urlblock = 'set url ' + '"*.' + $fline + '"'     #set url Quote Asterisk dot object-from-csv endquote eg: "*.zzz.com" or "*.1.2.3.4"
    $wild = 'set type wildcard'  #output set type wildcard
    $act = 'set action block'   #output set action block
    $nxt = 'next' #output next
    
    $editnum
    $urlblock
    $wild
    $act
    $nxt
    $counter1 = $counter1 + 1
}

$contentout | Out-File $fileout -Append
Add-Content -Path $fileout -Value "end"   #output end
Add-Content -Path $fileout -Value "end"   #output end

The input file contains (currently) 4 lines but could be over 1000 lines.

  1. 111.222.223.224
  2. 8.8.8.8
  3. zzz.com
  4. defabc.com.au

This is what I want the output to be:

config webfilter urlfilter

edit 1

set name "Test URL-Block"

config entries

edit 1

set url "*.111.222.223.224"

set type wildcard

set action block

next

edit 2

set url "*.8.8.8.8"

set type wildcard

set action block

next

edit 3

set url "*.zzz.com"

set type wildcard

set action block

next

edit 4

set url "*.defabc.com.au"

set type wildcard

set action block

next

end

end

This is the output I'm getting in the txt file:

config webfilter urlfilter

edit 1

set name "Test URL-Block"

config entries

e d i t 1

s e t u r l " * . C : \ S c r i p t T e s t s \ t e s t b l o c k . c s v "

s e t t y p e w i l d c a r d

s e t a c t i o n b l o c k

n e x t

end

end

Upvotes: 1

Views: 212

Answers (1)

Theo
Theo

Reputation: 61028

I would use Here-Strings for this:

$filein  = "C:\ScriptTests\testblock.csv"
$fileout = "C:\ScriptTests\testcli.txt"

# create a Here-String for the edits
$edit = @"
edit {0}
set url "{1}"
set type wildcard
set action block
next
"@

# create another Here-String for the complete file
$content = @"
config webfilter urlfilter
edit 1
set name "Test URL-Block"
config entries
{0}
end
"@

$counter = 1
$editBlocks = Get-Content $filein | ForEach-Object {
    # output the textblock with placeholders {0} and {1} filled in
    $edit -f $counter++, "*.$_"
}

# output the completed file with placeholder {0} replaced by the blocks, which are joined together with a Newline
# -PassThru will also display the completed text on screen. If you don't want that, remove that switch.
$content -f ($editBlocks -join [Environment]::NewLine) | Set-Content -Path $fileout -Force -PassThru

Output:

config webfilter urlfilter
edit 1
set name "Test URL-Block"
config entries
edit 1
set url "*.111.222.223.224"
set type wildcard
set action block
next
edit 2
set url "*.8.8.8.8"
set type wildcard
set action block
next
edit 3
set url "*.zzz.com"
set type wildcard
set action block
next
edit 4
set url "*.defabc.com.au"
set type wildcard
set action block
next
end

I don't know why you have an extra end in your desired output.. If that is needed, simply add it to the $content Here-String

Upvotes: 1

Related Questions