2

I have this Text file:

[Tabs]
MAILBOXSEND=1
MAILBOX=8
USERS=6
DOCUMENTS_Q=9
MED_WEBSERVCALLS_LOA=3
FCLMNA=1
INCZOOMFORM=1
USERSB=1
USERSB_ONE=1
DATAPRIV=1
MED_WEBSERVCALLS=2
TINVOICES=1
PORDERS=9
PORDERSTOTAL=1
LOGPART=1
LOGCOUNTERS=1
PARTMSG=1
[External Mail]
Send=Y
Hostname=Server
Domain=Domain
[email protected]
MyName=My Test
Port=25
SSL=0
[Search]
SUPPLIERS=5,1
StartButton=1
Ignore Case=0
PART=6,1

I'm Trying to capture all the text between [External Mail] to the Next [] Brackets Group,

I have this Regex which do the job and tested in Regex101, after all the testing's I found it's not working inside powershell:

$Text = Get-Content c:\text.txt
$Text -match '(?s)(?<=\[External Mail\]).*?(?=\[.*?\])'
or:
$Text | Select-String '(?s)(?<=\[External Mail\]).*?(?=\[.*?\])'

Nothing Return

Do you have any idea what I'm missing?

Thanks

2
  • Did you protected your \ ? Commented Jan 28, 2016 at 12:33
  • I would not use regex for this. Either convert to an object yourself or use something along the lines of Get-INIContent. Thank you for adding your code. Commented Jan 28, 2016 at 12:37

2 Answers 2

4

Looks like you are parsing an .INI file. Don't try to invent the wheel again, take leverage from existing code. This solution reads the .Ini file as nested hash tables that are easy to work with.

In case of link rot, here's the function from Scripting Guys archive:

function Get-IniContent ($filePath)
{
    $ini = @{}
    switch -regex -file $FilePath
    {
        "^\[(.+)\]" # Section
        {
            $section = $matches[1]
            $ini[$section] = @{}
            $CommentCount = 0
        }
        "^(;.*)$" # Comment
        {
            $value = $matches[1]
            $CommentCount = $CommentCount + 1
            $name = "Comment" + $CommentCount
            $ini[$section][$name] = $value
        } 
        "(.+?)\s*=(.*)" # Key
        {
            $name,$value = $matches[1..2]
            $ini[$section][$name] = $value
        }
    }
    return $ini
}

# Sample usage:
$i = Get-IniContent c:\temp\test.ini
$i["external mail"]

Name                           Value
----                           -----
Domain                         Domain
SSL                            0
Hostname                       Server
Send                           Y
MyName                         My Test
Port                           25
Myemail                        [email protected]

$i["external mail"].hostname
Server
Sign up to request clarification or add additional context in comments.

1 Comment

any easy way to replace a complete section? or just to create a new one with all the details(foreach or something) ?
3

Since you are trying to get a multiline regex match you need to be working against a single multiline string. That is the difference between your two cases of regex101 and PowerShell. Get-Content will be returning a string array. Your regex was not matching anything as it was only doing the test on single lines within the file.

PowerShell 2.0

$Text = Get-Content c:\text.txt | Out-String

PowerShell 3.0 of higher

$Text = Get-Content c:\text.txt -Raw

As I said in my comments you don't really need regex, in this way, for this type of string extraction. There are scripts that already exist to parse INI content. If you intend to be replacing content you would have to find the partner cmdlet Out-INIContent assuming it exists but I am sure someone made it. vonPryz's answer contains more information on the cmdlet

5 Comments

You just ninja-added the .Ini parser link I was so happy to show off with :-P
@vonPryz Yeah ... I had it in my earlier comment but though it would be better as part of an answer.
@JustCurious I told you how in my answer? I explained how to fix your problem. I have not tested your regex though..... is it still not working
@JustCurious You didn't make that clear... all you said was anyway to do it with regex. I will check your regex against the file myself.
@JustCurious Works fine for me $Text = Get-Content "c:\temp\text.txt" -Raw; $Text -match '(?s)(?<=\[External Mail\]).*?(?=\[.*?\])'; $Matches[0]. Just need to do the replace now..... I only used the semicolons as code in comments sucks. That is three lines

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.