Разделить строку на разрывы строк, сохраняя сегменты в кавычках - PullRequest
0 голосов
/ 14 февраля 2019

У меня есть CSV-файл, который читается в строку, и мне нужно разделить эту строку на разрывы строк, сохраняя сегменты в кавычках.Причина использования кавычек заключается в том, что некоторые поля файла имеют разрывы строк внутри.

По сути, у меня есть файл, подобный этому (я использую | для представления разделителя):

Это |а |линия

Это |линия тоже |"но это поле имеет

разрыв строки"

Это |другой |line

Я знаю, что могу использовать регулярное выражение с функцией .split(), но у меня проблемы с этим.Кто-нибудь может помочь?

Я ожидаю массив типа ["This is | a | line", "This is | a line too | but this field has\na line break", "This is | another | line"]

Ответы [ 4 ]

0 голосов
/ 14 февраля 2019

В качестве простейшего решения, мы можем сначала пометить (заменить некоторым идентификатором) line breaks, что мы не хотели бы разделить на .

Затем разделить все остальные разрывы строк и окончательно заменить сохраненные идентификаторы разрывов на line breaks again (\ n) .

arr = str.replace(/("[\s\S]*?")/g, (m, cg) => {
        return cg.replace(/\n/g, "LINE-BREAK-TO-PRESERVE");
      })
      .split('\n')
      .filter(i => Boolean(i.trim()))
      .map(i => i.replace(/LINE-BREAK-TO-PRESERVE/g, '\n'));

Над кодом необходимо заполнитьтвоя цель плавно:)

0 голосов
/ 14 февраля 2019

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

var arr = []
var inQuote = false;
var str = `This is | a | line
This is | a line too | "but this field has
a line break"
This is | another | line`
for (var pos = 0; pos < str.length; pos++) {
    if (str.charAt(pos) == "\n" && !inQuote) {
        arr.push(str.slice(0, pos));
        str = str.slice(pos + 1);
        pos = 0;
    } else if (str.charAt(pos) == '"') {
        inQuote = !inQuote;
        // if you want to get rid of the quotes:
        str = str.slice(0, pos) + str.slice(pos + 1)
        pos--
    }
}
arr.push(str)
console.log(arr)
0 голосов
/ 14 февраля 2019

Как и в другом ответе, может быть лучше использовать цикл, потому что даже при знании разделителя трудно проверить, находится ли кавычка в середине данных (как литерал) или она действует какцитата.

Тем не менее, это регулярное выражение должно служить цели для данного случая:

/(?<!\|\s+"[\w\s]+)\n/
console.log(
`This is | a | line
This is | a line too | "but this field has
a line break"
This is | another | line`.split(/(?<!\|\s+"[\w\s]+)\n/)
)

?<! является отрицательным взглядом сзади, что означает, что часть не в скобке(\n) сопоставляется, только если часть в скобке не соответствует.

Часть в скобке является разделителем (|), за которым следует более 1 пробела \s+ сразу за ним следует кавычка ", а затем смесь слов и пробелов.

Надеюсь, это поможет.\s+ можно изменить на \s* и [\w\s]+ также можно изменить на [^"]* по желанию.

Демо

0 голосов
/ 14 февраля 2019

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

("[^"\n]*)\r?\n(?!(([^"]*"){2})*[^"]*$)

Демонстрация: https://regex101.com/r/wL9sQ4/82

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