2

Hi I'm almost a newbie to Powershell. I need to read some specific lines in a text file and put them to different arrays. I have a file looking like this:

[Servers]
Server1
Server2
Server3
Server4
[IP]
10.10.10.10
10.10.10.20
10.10.30.30
192.168.1.2
192.168.1.4
[Path]
C:\Log\*.log
D:\Files\*.txt
D:\Files\*.csv
D:\Files\*.xml
[Gateway]
10.10.10.1
10.10.30.2
192.168.1.1

My problem is that I need to read the lines in [Servers] (sometimes 3 lines and sometimes a lot more) and put these in to a array. How do I select all lines between [Servers] and [IP] when I don't know the amount of lines?

alroc
  • 27,574
  • 6
  • 51
  • 97
RelaxDK
  • 89
  • 8

2 Answers2

0

Closely related: Grabbing specific sections of a txt file via Powershell

If it's acceptable to read the entire file into memory first:

$regex = '(?ms)\A.*?^\[Servers\]\s*\r?\n(.*?)(?:\r?\n\[.*|(?:\r?\n)?\Z)'
$servers = (Get-Content -Raw file.txt) -replace $regex, '$1' -split '\r?\n'

Refactored into a simple function that accepts the input file and the name of the section of interest:

function get-SectionLines([string] $LiteralPath, [string] $SectionName) {
  $regex = '(?ms)\A.*?^\[{0}\]\s*\r?\n(.*?)(?:\r?\n\[.*|(?:\r?\n)?\Z)' -f [regex]::Escape($SectionName)
  (Get-Content -Raw -LiteralPath $LiteralPath) -replace $regex, '$1' -split '\r?\n'
}

$servers = get-SectionLines file.txt Servers

Explanation:

  • Get-Content -Raw reads the entire file into memory as a single string.
  • -replace then operates on that one multi-line string, using a regex (regular expression) to match the entire input string, with a capture group ((...)) matching only the lines of interest, and replacing the entire string with just the capture group, effectively returning just the section's lines.
  • Finally, -split '\r?\n' splits the extracted multi-line string into an array of lines.

Explanation of the regex:

  • Inline regex options (?sm) turn on both the multi-line and the single-line option:

    • m means that ^ and $ match the start and end of each line rather than the input string as a whole.
    • s means that metacharacter . matches \n characters too, so that an expression such as .* can be used to match across lines.
  • \A matches the very start of the (multi-line) input, and \Z the very end.

  • \r?\n matches a single line break, both the CRLF and the LF variety.

  • (.*?) is the capture group that (non-greedily) captures everything inside the section.

  • (?:\r?\n\[.*|(?:\r?\n)?\Z) uses non-capturing groups ((?:...)) to match everything after the section of interest, which can either be the start of the next section (a line break followed by a [) or the end of the input file (either with or without a trailing line break).

  • Note that the regex matches the entire input string, and then replaces it with just the substring (range) of interest, captured in the 1st (and only) capture group ($1).

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

Method classic :

$found=$false
$Listword=(gc C:\temp\list.txt).Split("[]".ToCharArray())

$Servers=foreach ($item in $Listword)
{
    if ($item -eq "IP") { break }

    if ($item -eq "Servers") {$found=$true; continue}

    if ($found) {$item}
}

$Servers
mklement0
  • 382,024
  • 64
  • 607
  • 775
Esperento57
  • 16,521
  • 3
  • 39
  • 45