Извлечь и изменить определенные строки из текстового файла
Есть текстовый файл сетевых интерфейсов:
auto eth0 bri0
iface eth0 inet static
address 192.168.1.118/24
iface eth0.110 inet manual
vlan-raw-device eth0
iface bri0 inet static
address 192.168.110.1/24
bridge_ports eth0.110
bridge_stp on
bridge_maxwait 10 ```
Необходимо взять адрес у eth0 и заменить его на другой, например 192.168.1.13.
Я сделал класс, который получает все интерфейсы и ip:
public class IpChangeService
{
private readonly string[] configFile;
private List<string> interfaceName = new List<string>();
private List<string> ipAddress = new List<string>();
private string currentAdapter;
public IpChangeService(string[] configFile, string currentAdapter)
{
this.configFile = configFile;
this.currentAdapter = currentAdapter;
}
public (IList<string> iface, IList<string> ipAddress) GetCurrentInterfaces()
{
foreach (var line in configFile)
{
if (line.Contains("iface") && line.Contains("inet static"))
{
if (interfaceName != null)
{
var str = line.Split(' ')[1] + " ";
var strWithoutSpaces = str.Replace(" ", "");
interfaceName.Add(strWithoutSpaces);
}
}
if (interfaceName!=null && line.Contains("address"))
{
// see http://stackoverflow.com/questions/4890789/regex-for-an-ip-address
ipAddress.Add(Regex.Match(line, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}").Value);
}
}
return (interfaceName, ipAddress);
}
public int GetCurrentInterfaceIndex()
{
return interfaceName.IndexOf(currentAdapter);
}
Ну а в основной программе получаю данные и пытаюсь записать, но чувствую, что так не правильно, к тому же не работает нормально (криво вставляет адрес)! И пока не знаю, как правильно выделить ip без хардкода по индексу.
iface eth0 inet static
address 192.168.1.118/24168.1.13/24
private static void Main(string[] args)
{
var fileName = $"{AppDomain.CurrentDomain.BaseDirectory}interfaces";
var inputLines = File.ReadAllLines(fileName, Encoding.Default);
string interfaceName;
string ipAddress;
var ipChangeService = new IpChangeService(inputLines, "eth0");
var currentIface = ipChangeService.GetCurrentInterfaces();
var index = ipChangeService.GetCurrentInterfaceIndex();
interfaceName = currentIface.iface[index];
ipAddress = currentIface.ipAddress[0]; //FIXME: ХАРДКОД!
Console.WriteLine(interfaceName);
var s2 = "192.168.1.113/24"; // ip на который заменяем строчку
var configText = File.ReadAllText(fileName, Encoding.Default);
configText = configText
.Remove(configText.IndexOf(currentIface.ipAddress[0], StringComparison.Ordinal), ipAddress.Length)
.Insert(configText.IndexOf(currentIface.ipAddress[0], StringComparison.Ordinal), s2);
using (var file = new StreamWriter(fileName))
{
file.Write(configText);
}
Console.ReadKey();
}
Но самое главное, не понятно, как выделить ip адрес именно eth0 из всех существующих (их может быть несколько). А после заменить именно эту подстроку.
Ответы (2 шт):
Попробуй вот так :
на входе
private void button2_Click(object sender, EventArgs e)
{
string searchFor = "iface eth0";
bool IsFoundIface = false;
string path = "data.txt";
int foundindex=0;
string port="";
int size;
if (File.Exists(path))
{
var dataFile = File.ReadAllLines(path);
size= dataFile.Length;
for (int i = 0; i < dataFile.Length; i++)
{
if (dataFile[i].IndexOf(searchFor, StringComparison.Ordinal) != -1)
{
IsFoundIface = true;
}
if (IsFoundIface && dataFile[i+1].IndexOf("address", StringComparison.Ordinal) != -1)
{
var splitonport = dataFile[i + 1].Split('/');
foundindex = i + 1;
port = splitonport[1];
break;
}
}
string[] newData = new string[size];
for (int i = 0; i < size; i++)
{
if (i != foundindex)
{
newData[i] = dataFile[i];
}
else
{
newData[i] = string.Format(" address {0}/{1}", textBox1.Text, port);
}
}
File.WriteAllLines(path,newData);
}
}
на выходе получаем
auto eth0 bri0
iface eth0 inet static
address 192.168.1.13/24
iface eth0.110 inet manual
vlan-raw-device eth0
iface bri0 inet static
address 192.168.110.1/24
bridge_ports eth0.110
bridge_stp on
bridge_maxwait 10 ```
Если надо просто заменить, то можно поступить так:
Делаем метод для поиска строчки с Ip:
private static (string Line, int Index) GetIp(IList<string> lines, string search) { var adresses = lines.Select((Line, Index) => (Line, Index)).Where(x => x.Line.Contains("address")); foreach (var item in adresses) { for (int i = item.Index; i >= 0; i--) { if (lines[i].Contains(search)) { return item; } } } return default; }Поясняю:
- Преобразовываем все строчки в
(значение, индекс)и забираем только те, которые имеютaddress. В результате у нас будут все строки с ip адресами и их индекс в списке. - Сопоставляем ip с интерфейсами - просто пробегаем циклом
forот места, где строчка с ip и до искомой строки вверх. Если интерфейс подходит под искомый, то возвращаем ip и его индекс.
- Преобразовываем все строчки в
Дальше все просто:
Считываем из файла все построчно:
var lines = File.ReadAllLines("File.txt");Находим нужный нам ip:
var (Line, Index) = GetIp(lines, "iface eth0");Меняем в строке ip адрес:
lines[Index] = lines[Index].Replace(Line.Split().LastOrDefault(), "0.0.0.0");Ну, осталось сохранить:
File.WriteAllLines("File.txt", lines);
Результат:
auto eth0 bri0
iface eth0 inet static
address 0.0.0.0
iface eth0.110 inet manual
vlan-raw-device eth0
iface bri0 inet static
address 192.168.110.1/24
bridge_ports eth0.110
bridge_stp on
bridge_maxwait 10 ```
