Добавьте двоеточие к пути к файлу после буквы диска (т.е. измените /c/ или c/ на c:/) в Java

По сути, я получаю путь к файлу из строки внутри CSV-файла. Однако по какой-то причине программа, создающая файл CSV, удаляет двоеточие из строки, поэтому я получаю путь к файлу, который не работает внутри Java. Типичный вывод — /x/Rest/Of/Path, где x — буква диска, но иногда может быть x/ вместо /x/. По сути, мне нужно добавить двоеточие после буквы диска, если его еще нет; изменение /x/ или x/ на x:/. Я уверен, что в основном это делается с помощью регулярных выражений, но я все еще пытаюсь понять основы регулярных выражений, поэтому я не уверен, как это написать. Заранее благодарю за любую помощь.


person DGolberg    schedule 30.04.2013    source источник


Ответы (1)


Вот, попробуйте это и изучите, чтобы узнать, как это работает:

String path = "/C/Rest/Of/Path";
Pattern p = Pattern.compile("^(/?[CDEFGH])/");
Matcher m = p.matcher(path);
String pathWithColon = m.replaceAll("$1:/");

Вот руководство:

  1. ^ известен как якорь. Он соответствует самому началу строки. Без него это регулярное выражение также соответствовало бы /foo/C/Rest/Of/Path, а нам это не нужно.
  2. ? может означать разные вещи, в зависимости от того, где он появляется. Если он не следует сразу за открывающей скобкой (, не следует сразу за квантификатором *, +, другой ?, {n}, {m,n}, не появляется внутри класса символов< /em> [], а не экранированный \?, то это квантификатор, означающий "0 или 1 предыдущего объекта", в данном случае /. Думайте об этом как о «необязательном» операторе.
  3. [CDEFGH] известен как класс символов. Это означает: «Любой один из этих символов». Вы можете отменить класс символов следующим образом: [^CDEFGH]; это будет означать «Любой один символ, но не эти». Если вы хотите принять любую заглавную букву, вы можете использовать диапазон: [A-Z]. Если вы хотите принять любое письмо, то: [a-zA-Z].
  4. Круглые скобки, окружающие большую часть регулярного выражения, известны как группа захвата или группа захвата. Он «спасает» все, что «поймано» между ними.
  5. Во время замены вы можете ссылаться на «сохраненные» (захваченные) группы по $1, $2, $3 и так далее. (Таким образом, вы можете захватить более одной группы; каждая захватываемая группа нумеруется в порядке открывающей скобки.) Обратите внимание, что в приведенном выше примере я также захватил /?, поэтому, если косая черта существует, то она будет существовать в вывод тоже, а если нет, то нет.

Приятного обучения!

ИЗМЕНИТЬ

Я должен был привести пример более простого подхода для начала. Мои извинения. Это также подойдет:

String path = "/C/Rest/Of/Path";
path = path.replaceAll("^(/?[CDEFGH])/", "$1:/");

Использование скомпилированного шаблона только добавляет эффективности. Например, если вы собираетесь заменить массив из 10 000 путей, вы должны скомпилировать шаблон один раз, а затем использовать сопоставитель для замены каждого пути в цикле. (Без компиляции движку приходится анализировать шаблон с нуля для каждого встречающегося пути.)

person slackwing    schedule 30.04.2013
comment
Вау, рад, что спросил. Забудьте о регулярном выражении, я еще даже не был знаком с частью Matcher. Теперь я лучше понимаю регулярное выражение, просто не уверен, что в нем делают () . Я знаю, что ^ указывает начало строки, а /? означает, если первый / существует правильно? тогда [] для поиска одного из содержащихся символов перед другим /. - person DGolberg; 01.05.2013
comment
@DGolberg - я отредактировал свой ответ с объяснением частей. Пожалуйста, не стесняйтесь комментировать снова, если что-то неясно. - person slackwing; 01.05.2013
comment
Красиво, спасибо за заметки! Они были намного полезнее, чем многие другие сайты, которые я посетил в отношении регулярных выражений! Первоначально я пытался сделать что-то с помощью .replace();, но быстро понял, что мне придется использовать что-то еще, например .replaceall();, но я не был знаком с ним. Мой опыт до сих пор заключался в основном в замене тега формата файла в конце имени файла или проверке определенного слова в строке (в основном .contains()). - person DGolberg; 01.05.2013
comment
Основываясь на вашем последнем редактировании, исходный ответ, вероятно, в любом случае более правильный для моей ситуации, но второй экземпляр также пригодится. В основном я загружаю список завершенных корневых папок проекта в массив, а затем просматриваю их, чтобы получить список их файлов для загрузки. - person DGolberg; 01.05.2013
comment
@DGolberg - понятно; похоже, вы были на правильном пути. Оглядываясь назад, регулярное выражение кажется простым, но может быть пугающим до первого шага. Удачи в остальном! - person slackwing; 01.05.2013
comment
Конечно есть! Спасибо еще раз за помощь! - person DGolberg; 01.05.2013