Need to split up a large patterned text file into multiple text files.

Chad Killion
Chad Killion used Ask the Experts™
on
Hello,

I have a 5200 line text file full of DNS zone information.  It is formatted such with line 1 being the SOA record, and the last 2 lines of the zone are "Success..." and then "----" and then it repeats with the next zone.  An example of the top 2 records looks like the following:

domain1.com. SOA dauth5.server.com. contact.domain1.com. 2018020603 10800 3600 604800 10800
webmail.domain1.com. CNAME  domain1.com.
domain1.com. NS  dauth5.server.com.
domain1.com. MX 10 mail3.serverhosting.com.
domain1.com. A  255.255.138.2
mail.domain1.com. CNAME  mail3.serverhosting.com.
pop.domain1.com. CNAME  pop.serverhosting.com.
domain1.com. MX 10 mx1-us1.ppe-hosted.com.
www.domain1.com. CNAME  domain1.com.
domain1.com. NS  dauth6.server.com.
domain1.com. MX 20 mx2-us1.ppe-hosted.com.
smtp.domain1.com. CNAME  smtp.serverhosting.com.
SUCCESS: Getting information for Domain 'domain1.com' complete.
---------------
domain2.com. SOA dauth5.server.com. admin.server.com. 2018052503 900 600 86400 10800
domain2.com. A  192.168.255.2
domain2.com. MX 20 mx2-us1.ppe-hosted.com.
domain2.com. MX 10 mx1-us1.ppe-hosted.com.
www.domain2.com. CNAME  domain2.com.
mail.domain2.com. CNAME  mail4.serverhosting.com.
domain2.com. NS  dauth5.server.com.
domain2.com. NS  dauth6.server.com.
SUCCESS: Getting information for Domain 'domain2.com' complete.
---------------

Open in new window


I would like a powershell script that will take my file as in input, then split the file into multiple text files saved to a specific path.  The file name should be the very first word on line1 (domain1.com.text and domain2.com.text in the scenario above), then they should contain all lines up to the "Success:, and the following------" lines.  Those can be discarded.  So after processing the script given the text file above, I would be left with the following:

c:\temp\domain1.com.txt which would look like:
domain1.com. SOA dauth5.server.com. contact.domain1.com. 2018020603 10800 3600 604800 10800
webmail.domain1.com. CNAME  domain1.com.
domain1.com. NS  dauth5.server.com.
domain1.com. MX 10 mail3.serverhosting.com.
domain1.com. A  255.255.138.2
mail.domain1.com. CNAME  mail3.serverhosting.com.
pop.domain1.com. CNAME  pop.serverhosting.com.
domain1.com. MX 10 mx1-us1.ppe-hosted.com.
www.domain1.com. CNAME  domain1.com.
domain1.com. NS  dauth6.server.com.
domain1.com. MX 20 mx2-us1.ppe-hosted.com.
smtp.domain1.com. CNAME  smtp.serverhosting.com.

Open in new window


and c:\temp\domain2.com.text which would look like:
domain2.com. SOA dauth5.server.com. admin.server.com. 2018052503 900 600 86400 10800
domain2.com. A  192.168.255.2
domain2.com. MX 20 mx2-us1.ppe-hosted.com.
domain2.com. MX 10 mx1-us1.ppe-hosted.com.
www.domain2.com. CNAME  domain2.com.
mail.domain2.com. CNAME  mail4.serverhosting.com.
domain2.com. NS  dauth5.server.com.
domain2.com. NS  dauth6.server.com.

Open in new window


I think I will end up with a few hundred text files, but this would save me a ton of time!  Thanks in advance!
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
IT / Software Engineering Consultant
Top Expert 2016
Commented:
Here's a straight forward approach with PS.  I'm sure a shorter more cryptic version could be fashioned, but this seems to get the job done here.   Adjust the paths near the top and give it a try.

$InFile = "B:\EE\EE29138324\in.txt"
$DestDir = "B:\EE\EE29138324"
$Data = Get-Content $InFile
$OutFile = ""
foreach($Line in $Data)
{
    if($Line.SubString(0,8) -eq "SUCCESS:" -or $Line -eq "---------------"){
        $OutFile = ""
    } else {
        if($OutFile -eq "") {
            $OutFile = $Line.Split()[0].TrimEnd('.')
        }
        $Line >> "$DestDir\$OutFile.txt"
    }
}

Open in new window


»bp

Commented:
I prefer to code functions to make the utility more flexible and straightforward to move to a module. I have assumed that the line before the -------- separator is always SUCCESS, is it sometimes FAILURE?
function ConvertTo-SplitDNSZoneInfoFile
{
    [CmdletBinding()]
    Param
    (
        [String]$InputFilePath = "D:\DNSZoneInfo\DNSZoneInfo.txt",
        [String]$OutFileDirectory = "D:\DNSZoneInfo"
    )

    if ((Test-Path $InputFilePath) -and (Test-Path $OutFileDirectory))
    {
        $InputFile = Get-Content $InputFilePath
        $OutFileName = ""
        foreach ($line in $InputFile)
        {
            if ([String]::IsNullOrEmpty($OutFileName))
            {
                if ($line -notlike "--*")
                {
                    $OutFileName = $line.Split(" ")[0] + "txt"
                    $OutFilePath = Join-Path -Path $OutFileDirectory -ChildPath $OutFileName
                }
            }
            else
            {
                if ($line -like "SUCCESS*" -or $line -Like "--*")
                {
                    $OutFileName = ""
                }
                else
                {
                    $line | Out-File $OutFilePath -Append
                }
            }
        }
    }
    else
    {
        Write-Warning "Unable to find either $InputFilePath or $OutFileDirectory"
    }
}

ConvertTo-SplitDNSZoneInfoFile

Open in new window

Author

Commented:
Bill - Using your method, the top line of the resulting text files is missing...example:

domain1.com. SOA dauth5.server.com. contact.domain1.com. 2018020603 10800 3600 604800 10800

Doesn't appear in the resulting file on any of the files created.  The first line should always be the SOA line.

Brent - Using your method, the SOA line does appear, but not in order...its like the order gets mixed up and the SOA line appears on line 5 or 6 but not line 1 each time as it should?
Expert Spotlight: Joe Anderson (DatabaseMX)

We’ve posted a new Expert Spotlight!  Joe Anderson (DatabaseMX) has been on Experts Exchange since 2006. Learn more about this database architect, guitar aficionado, and Microsoft MVP.

Bill PrewIT / Software Engineering Consultant
Top Expert 2016

Commented:
I tested with what you posted and it worked fine here, my test files attached.  If you want to post your actual input file I can test here, it may be that that first line has some extra special characters that are causing a problem...

in.txt
domain1.com.txt
domain2.com.txt


»bp

Author

Commented:
I took your in file and and appended 2 real records to it and I have the same results, very odd...no SOA line at the top of any of the resullting file...
dom_dns.txt
1talltrees.com.txt
456jobs.com.txt
domain1.com.txt
domain2.com.txt
Bill PrewIT / Software Engineering Consultant
Top Expert 2016

Commented:
I took your dom_dns.txt file, ran it through the script I posted here, and the 4 result files have the first line here.

What version of powershell do you have?

And did you make any changes to the script I posted?


»bp

Author

Commented:
Can't explain it...but it is working now.  I just re-copied the script and changed lines 1 and 2 and re-ran the script and SOA shows up as line #1 now.  Sorry for wasting your last 30 minutes!  Thanks so much for the help!
Bill PrewIT / Software Engineering Consultant
Top Expert 2016

Commented:
No worries, glad it's working there now.


»bp

Commented:
I checked my code and it consumed the first line when changing the output file name rather than outputting it.  I have also added a switch to indicate that you want to delete the output file if it exists.
function ConvertTo-SplitDNSZoneInfoFile
{
    [CmdletBinding()]
    Param
    (
        [String]$InputFilePath = "D:\DNSZoneInfo\DNSZoneInfo.txt",
        [String]$OutFileDirectory = "D:\DNSZoneInfo",
        [Switch]$Clobber
    )

    if ((Test-Path $InputFilePath) -and (Test-Path $OutFileDirectory))
    {
        $InputFile = Get-Content $InputFilePath
        $OutFileName = ""
        foreach ($line in $InputFile)
        {
            if ([String]::IsNullOrEmpty($OutFileName))
            {
                if ($line -notlike "--*")
                {
                    $OutFileName = $line.Split(" ")[0] + "txt"
                    $OutFilePath = Join-Path -Path $OutFileDirectory -ChildPath $OutFileName
                    if ($Clobber -and (Test-Path $OutFilePath))
                    {
                        Remove-Item $OutFilePath
                    }
                }
            }
            if ($line -like "SUCCESS*" -or $line -Like "--*")
            {
                $OutFileName = ""
            }
            else
            {
                $line | Out-File $OutFilePath -Append
            }
        }
    }
    else
    {
        Write-Warning "Unable to find either $InputFilePath or $OutFileDirectory"
    }
}

ConvertTo-SplitDNSZoneInfoFile -Clobber

Open in new window

Author

Commented:
Thanks again, and Brent the second one worked out great as well!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial