Регулярное выражение, чтобы соответствовать чему-либо, но не более двух пробелов - PullRequest
0 голосов
/ 26 апреля 2011

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

999            date               Doe, John E.              London            123456789

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

$line =~ s/([^\s{2,}]*,[^\s{2,}]*)/"$1"/g;

Я думаю, он должен найти любую запятую и что-нибудь рядом с ней, пока не найдет два или более пробела, но это не работает. Спасибо за помощь.

Ответы [ 5 ]

8 голосов
/ 26 апреля 2011

Вы запросили что-нибудь , кроме 2 или более пробелов.

Я согласен, что unpack - более естественный способ сделать это. Но split - это способ использования печенья в форме узора. Все, что не в этом шаблоне, является полем возврата. Итак, это:

@fields = split /\h{2,}/, $line;
$line = join(" " x 2 => map { "($_)" } @fields);

может быть достаточно.

2 голосов
/ 26 апреля 2011

Если это данные фиксированной ширины (и я думаю, это так), лучше использовать unpack (или просто старый substr и т. Д.), А не регулярные выражения.

1 голос
/ 26 апреля 2011

Представленный вами образец текста, кажется, разделен либо табуляцией, либо пробелами (выравнивание по столбцу?).Важно знать, какие, или регулярное выражение не будет работать.Также важно знать, является ли шаблон единообразным по всему файлу.

Если он выровнен по столбцам, самый простой и, вероятно, самый безопасный способ - просто отсчитать символы.Например:

s/(^.{20})(\S*)  /$1"$2"/;

(Вам нужно будет самостоятельно настроить число 20. Я только что приблизительно).

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

При работе с файлами такого типа я не думаю, что безопаснее использовать общий поиск.Если вы рассчитываете, что запятые появляются только в именах, рано или поздно вы найдете кого-то, кто подумал, что «Бронкс, Нью-Йорк» должен быть в поле города, и ваше регулярное выражение будет испорчено.

Aнесколько более строгое, но сложное регулярное выражение будет включать в себя предыдущие поля:

$date='\d{2}-\d{2}-\d{2}'; # this might work for dates such as 11-10-23

s/^(\d+\s+$date\s+)(\S+)  /$1"$2"/;

То же самое здесь, если поле имени недостаточно велико, чтобы поместиться в две кавычки, оно не будет добавлено.Вы должны проверить свой файл и посмотреть, так ли это.Если это так, вам придется как-то с этим справиться.

Иногда я нахожу, что помещение регулярных выражений определенного поля в отдельные переменные помогает с удобочитаемостью, например, с $ date выше.

Хорошоудачи!

1 голос
/ 26 апреля 2011

Попробуйте это:

s/.*  \K(.*),(.*?)  /"$1,$2"  /

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

Ваш подход тоже может сработать, если вы правильно поняли синтаксис негативных запросов.

1 голос
/ 26 апреля 2011

[] содержит диапазон символов, которые допускаются при этом возможно, 2 пробела не является символом.

Может быть:

$line =~ s/  (.*? .*?)  /  "\1"  /g;

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

$line =~ s/  (\w+?, [\w ]+?.)  /  "\1"  /g;

Чтобы избежать повторения пробела в замене, можно использовать утверждения для осмотра, которые также могут решить проблему элементов в начале и конце строки:

$line =~ s/(?<=^|  )(\w+?, [\w ]+?.)(?=$|  )/"\1"/g;

Также будьте осторожны с исходным форматом - вы уверены, что он не только выровнен по столбцу? (В этом случае достаточно длинное имя или дата могут не содержать пробелов между столбцами 2+).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...