2016-01-04 3 views
2

У меня есть необычный проект, в котором мне нужно получить текст после второго последнего появления символа «\», эффективно предоставив мне последние два каталога в Следующий пример строки:Получить строку, которая следует за вторым последним вводом символа/строки

  • D: \ Архив Каталог \ 2015-12-31 \ PM SerialNo_01
  • D: \ Archive Directory \ 2016-01-01 \ SerialNo_02
  • D: \ Directory \ Archive января 2016 \ SerialNo_03

Желаемый результат, соответственно:

  • 2015-12-31 PM \ SerialNo_01
  • 2016-01-01 \ SerialNo_02
  • января 2016 \ SerialNo_03

Я хотел бы сделайте это как можно чище, и желательно в одной строке кода для каждой строки.

Этот вопрос отвечает мной после того, как вы ничего не обнаружили в Stack Overflow о том, чтобы найти второе-последнее вхождение (или, если на то пошло, любое N-ое вхождение в обратном направлении) строки или символа в строке в C#. Если сообщество выяснит, что этот вопрос дублируется или кажется, что это слишком непонятный случай, я готов его удалить.

Редактировать: Уточнено, что мне не нужно делать это как список строк; они будут запускаться по одному за раз. Я динамически добавляю их в качестве элементов управления переключателями в форму.

+0

Если Вы заинтересованы в регулярном выражении, [ '\\ [^ \\] + \\ $' (*.)] (Https: // regex101.com/r/cB7cE4/1) с флагами 'gm'. – Tushar

ответ

3

Вам не нужно регулярное выражение, вы можете рассчитывать на встроенном в обработке путей, предоставленной .NET.

var input = new List<string> { 
    @"D:\Archive Directory\2015-12-31 PM\SerialNo_01", 
    @"D:\Archive Directory\2016-01-01\SerialNo_02", 
    @"D:\Archive Directory\January 2016\SerialNo_03" 
}; 

var result = input.Select(s => Path.Combine(Directory.GetParent(s).Name, Path.GetFileName(s))); 

Урожайность:

2015-12-31 PM\SerialNo_01 
2016-01-01\SerialNo_02 
January 2016\SerialNo_03 

Тогда вам не нужно беспокоиться о крайних случаях, или даже кросс-совместимость ОС.

+0

Выполняется ли это, если часть «SerialNo_0x» является каталогом, а не файлом? По какой-то причине это не будет компилироваться даже тогда, когда я изменил «Path.GetFileName (s)» на «Path.GetDirectoryName (s)»; Я получил сообщение «Can not convert char to string» в обеих ссылках на 's'. –

+0

Я использую каждый из путей отдельно (не как список, разделенный запятыми), но я не думаю, что это было бы проблемой? –

+0

Он не знает, является ли это каталогом или файлом, но выше будет работать для обоих. Ошибка состоит в том, что вы, вероятно, используете ввод как строку, а не список строк. – Rob

1

Я смог придумать решение после настройки кода с this clever answer.

myString.Split('\\').Reverse().Take(2).Aggregate((s1, s2) => s2 + "\\" + s1); 

Это будет разделить строку на каждой обратной косой черты, а затем в обратном результирующий массив строк и принимать только последние два элемента, прежде чем конкатенации их вместе, теперь в обратном порядке, что дает желаемого результата.

+2

Это ужасно расточительный способ получить подстроку ... Обычный LastIndexOf работает быстрее и не производит безумного количества строк/объектов в процессе. –

+0

Согласен - это было первое, что я пробовал, но я не ищу последний индекс обратной косой черты, я ищу второй его индекс. Можете ли вы показать мне, как использовать LastIndexOf для этого? –

+1

Я бы поставил вопрос на SO, спрашивая: «Есть ли LastIndexOf, который может начать поиск назад из заданной позиции» ... Возможно, кто-то будет искать MSDN для меня и дать ответ. Затем найдите ответы в поисковых запросах, как http://stackoverflow.com/questions/2571716/find-nth-occurrence-of-a-character-in-a-string и copy-paste. –

1

Вы также можете найти нужные детали.

(?<=\\)[^\\]*\\[^\\]*$ 

См. Демонстрационную версию.

https://regex101.com/r/fM9lY3/56

string strRegex = @"(?<=\\)[^\\]*\\[^\\]*$"; 
Regex myRegex = new Regex(strRegex, RegexOptions.Multiline); 
string strTargetString = @"D:\Archive Directory\2015-12-31 PM\SerialNo_01" + "\n" + @"D:\Archive Directory\2016-01-01\SerialNo_02" + "\n" + @"D:\Archive Directory\January 2016\SerialNo_03"; 

foreach (Match myMatch in myRegex.Matches(strTargetString)) 
{ 
    if (myMatch.Success) 
    { 
    // Add your code here 
    } 
} 
0
If you still want to use Regex, you can use 

Match match = Regex.Match(inputString,@".:\\.*\\(.*\\.*)"); 

if(match.success) 
{ 
Result = match.Groups[1].value; 
} 

The first group in match will give the required result 

Для многократного использования результатов матчей вместо матча

0
List<string> paths = new List<string> { 
        @"D:\Archive Directory\2015-12-31 PM\SerialNo_01", 
        @"D:\Archive Directory\2016-01-01\SerialNo_02", 
        @"D:\Archive Directory\January 2016\SerialNo_03" }; 

var requiredPaths = paths.Select(item=> string.Join(@"\",item.Split('\\'). 
           Reverse().Take(2).Reverse())); 
Смежные вопросы