I am new to c#. I have text file with data in it but I want to read particular block line data.
Here address can occur multiple times in text file.
Something here...
... ... ...
interface "system"
address 10.4.1.10/32
no shutdown
exit
something here...
... ... ...
address 101.4.1.11/32
but i want to capture within this
interface "system"
address 10.4.1.10/32
no shutdown
exit
I want to capture this ip from the block:
10.4.1.10
I tried this code:
int counter = 0;
string line;
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader("c:\\test.txt");
while((line = file.ReadLine()) != null)
{
Console.WriteLine (line);
counter++;
}
file.Close();
// Suspend the screen.
Console.ReadLine();
Expected Output:
my expected output is to capture the ip address from that block ie.10.4.1.10 that ip is inside "interface system" block.. that makes that address as unique.. as there can be many ips with keyword address. So i want to take address which is inside interface system block.
Please let me know how i can capture particular string from the block.
Regular Expressions are perfectly suited to handle this type of "problem". The following console app demonstrates how to use Regex
to extract the desired IP address from the targeted string block.
private static readonly string IPV4_PATTERN = "[0-9./]";
private static readonly string IPV4_IPV6_PATTERN = "[A-Z0-9:./]";
static void Main(string[] args)
{
TestSearchFile();
}
private static string ParseIpWithRegex(string textToSearch, string startBlock, string endBlock)
{
var pattern = $@"{startBlock}\D*\s*({IPV4_IPV6_PATTERN}+).*{endBlock}";
var ms = Regex.Match(textToSearch, pattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
if (ms.Groups.TryGetValue("1", out var g))
{
return g.Value;
}
return string.Empty;
}
private static void TestSearchFile()
{
var sep = Environment.NewLine;
var ipAddress6 = "2001:db8:85a3:8d3:1319:8a2e:370:7348";
var ipAddress4 = "10.4.1.10/32";
var t = "Something here..." + sep;
t += "... ... ... " + sep;
t += "interface \"system\"" + sep;
t += "address " + ipAddress4 + sep;
t += "no shutdown" + sep;
t += "exit" + sep;
t += "something here..." + sep;
t += "address 101.4.1.11/32" + sep;
t += "... ... ... " + sep;
var startBlock = "interface \"system\"";
var endBlock = "exit";
var ip = ParseIpWithRegex(t, startBlock, endBlock);
Console.WriteLine($"IP: {ip}");
}
I've included two IP address patterns IPV4_PATTERN
for IPV4 only as well as IPV4_IPV6_PATTERN
for both IPV4 and IPV6. Select the one you feel is most appropriate. Although the IPV4_IPV6_PATTERN
would apply to both IP versions I believe it improves performance slight when the search is narrowed by using the narrowest pattern.
Don't forget to import the Regex
reference:
using System.Text.RegularExpressions;
The method "ParseIpWithRegex" uses a Regex
pattern constructed by using the string that signifies the start of the targeted block and the string that signifies the end of that block. Nestled within that pattern is the regular expressions class definition that defines the IP address pattern we wish to isolate as a group.
$@"{startBlock}\D*\s*({IPV4_IPV6_PATTERN}+).*{endBlock}";
It should be noted that the curly brackets are just for string interpolation and have (in this case) nothing to do with the actual regular expression!
After the "startBlock" we see "\D*". This means that after the "startBlock" include in the search all non-numeric characters (where the "star" indicates to expect zero to infinitely many). Then we see "\s*" which means to include all white space (including new line characters since I included RegexOptions.Singleline
).
The IP address pattern is in brackets "()" which instructs Regex
to create groups. In this case, behind the IP address pattern (in the above code example IPV4_IPV6_PATTERN
) there is a "+" symbol. This indicates that there MUST be at least one of the characters that is in the IP address Regex class definition in order to be considered a "match".
After that we see ".*" in front of the "endBlock". This means to look for any character--including the "new line" character (zero to infinitely many) in from of the "endBlock" string.
If you have any questions, please leave a comment.
EDIT
From your button onclick
method you will call SearchFileForIp
. You will need to change myTextBox
to match your code.
You should also decide whether you will be searching IPV4 or both IPV4 and IPV6 and select the appropriate variable IPV4_PATTERN
or IPV4_IPV6_PATTERN
.
private void SearchFileForIp()
{
var fileName = "c:\\test.txt";
using var sr = new StreamReader(fileName);
string fileContent = sr.ReadToEnd();
var startBlock = "interface \"system\"";
var endBlock = "exit";
var ip = ParseForIpRegex(fileContent, startBlock, endBlock);
myTextBox.Text = ip; //Change this to match your code
}
private readonly string IPV4_PATTERN = "[0-9./]";
private readonly string IPV4_IPV6_PATTERN = "[A-Z0-9:./]";
private string ParseForIpRegex(string textToSearch, string startBlock, string endBlock)
{
var pattern = $@"{startBlock}\D*\s*({IPV4_PATTERN}+).*{endBlock}";
var ms = Regex.Match(textToSearch, pattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
if(ms.Groups.Count > 0)
{
return ms.Groups[1].Value;
}
//For .Net Core apps
//if (ms.Groups.TryGetValue("1", out var g))
//{
// return g.Value;
//}
return string.Empty;
}
In addition to the 2 answers with Regex solutions, If address line comes always after interace "system"
, than a simple for loop can do the job.
interface "system"
address 10.4.1.10/32
no shutdown
exit
So We go thorugh file lines and check if line is interace "system"
than take the next value and parse it to string of ip address.
public static string GetIpAddressFromFile(string fileName, string startLine)
{
var lines = File.ReadAllLines(fileName);
var ipAddress = string.Empty;
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i].Trim();
if (line != startLine) continue;
var addressLine = lines[i + 1].Trim().Replace("address", "");
ipAddress = addressLine.Substring(0, addressLine.IndexOf("/", StringComparison.Ordinal));
break;
}
return ipAddress.Trim();
}
Lets assume you that your file is inconsistent and address does not comes first after interface "system"
interface "system"
...
address 10.4.1.10/32
no shutdown
exit
So in this case we put all lines between interface "system"
and exit
in list of strings, Or dictionary and fetch the address key.
public static string GetIpAddressFromFile(string fileName, string startLine, string endLine)
{
var lines = File.ReadAllLines(fileName);
var ipAddress = string.Empty;
var state = false;
var results = new Dictionary<string, string>();
foreach (var t in lines)
{
var line = t.Trim();
if (line == startLine)
state = true;
if (line == endLine)
state = false;
if (!state) continue;
var s = line.Split(" ");
results.TryAdd(s[0], s[1]);
}
var result = results.GetValueOrDefault("address");
if (result != null)
{
ipAddress = result.Substring(0, result.IndexOf("/", StringComparison.Ordinal));
}
return ipAddress;
}
Usage:
var startLine = "interface \"system\"";
var endLine = "exit";
var ip = GetIpAddressFromFile(@"File.txt", startLine);
//Or
var ip = GetIpAddressFromFile1(@"File.txt", startLine, endLine);
Both methods are tested with your given example and return:
10.4.1.10
If the start of the block and the end of the block are well defined, in order to find the block you can simply:
string line;
System.IO.StreamReader file = new System.IO.StreamReader("c:\\test.txt");
while((line = file.ReadLine()) != null && !line.Equals(START_OF_BLOCK)); // 1.
while((line = file.ReadLine()) != null && !line.Equals(END_OF_BLOCK)) // 2.
{
// do something with the lines
}
file.Close();
In order to "extract" the string in a form of an IP address inside the block, you could, for example, use Regular expressions with a .NET Regex class, with previously finding the needed block:
"address"
Regexp.Match()
string line;
System.IO.StreamReader file = new System.IO.StreamReader("c:\\test.txt");
string pat = @"\b(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b";
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(pat);
while ((line = Console.ReadLine()) != null && !line.Equals(START_OF_BLOCK)); // 1.
while ((line = Console.ReadLine()) != null && !line.Equals(END_OF_BLOCK)) // 2.
{
if (line.Contains("address"))
{
System.Text.RegularExpressions.Match ip = reg.Match(line);
Console.WriteLine(ip);
break; // break if you are sure there's only one ip in that block
}
}
file.Close();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With