Использование регулярного выражения javascript для удаления нескольких обратных косых черт при сохранении специального символа \ n - PullRequest
1 голос
/ 23 апреля 2019

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

{
    "test": {
        "title": "line 1\\\\\\\nline2"
    }
}

Я пробовал различные шаблоны RegEx, используя замену.«Странно», они, кажется, работают, если есть четное количество обратных слешей, но не странное.

Этот пример с 2 обратными слешами работает:

"\\n".replace(/\\(?=.{2})/g, '');

В то время как этот пример с 3 не работает:

"\\\n".replace(/\\(?=.{2})/g, '');

Вот js в действии:

console.log('Even Slashes:');
console.log("\\n".replace(/\\(?=.{2})/g, ''));
console.log('Odd Slashes:');
console.log("\\\n".replace(/\\(?=.{2})/g, ''));

Ответы [ 3 ]

1 голос
/ 23 апреля 2019

Как я уже упоминал в моем предыдущем комментарии, здесь вы имеете дело с двумя различными escape-последовательностями:

  • \n - это escape-последовательность для символа новой строки, т.е. Unicode Character 'LINEFEED (LF) '(U + 000A)
  • \\ является escape-последовательностью для обратной косой черты, т. Е. Unicode-символ' REVERSE SOLIDUS '(U + 005C)

Хотя эти escape-последовательности представляют собой два символа в исходном коде , они фактически представляют только один символ в памяти.

Замечание:

const toEscaped = s => s.toSource().match(/"(.*)"/)[0];
['\n', '\\n', '\\\n', '\\\\n', '\\\\\n']
  .forEach(s => console.log(`There are ${s.length} character(s) in ${toEscaped(s)}`))

Это также относится к регулярным выражениям.\n фактически считается одним символом, поэтому наблюдатель (?=.{2}) также попытается захватить предшествующий \, поэтому вы, возможно, видите некоторую странность в том, как работает ваша замена.

Однако, основываясь на прочтении некоторых ваших комментариев, похоже, вы имеете дело с неправильными кодировками.Например, у вас могут быть случаи, когда пользователь вводит foo\nbar в поле ввода, которое интерпретируется как литерал \, за которым следует n (то есть "foo\\nbar"), и теперь вы хотите интерпретировать это как символ новой строкисимвол (т.е. "foo\nbar").В этом случае вы на самом деле не пытаетесь удалить \ символов, вы пытаетесь преобразовать последовательность символов \ + n в \n.

В следующем фрагменте кода показано, каквыполнить замены escape-последовательности для \\ и \n:

const toEscaped = s => s.toSource().match(/"(.*)"/)[0];
const toHex = s => Array.from(s).map((_, i) => s.charCodeAt(i).toString(16).padStart(2, '0')).join('+');
['\n', '\\n', '\\\n', '\\\\n', '\\\\\n']
  .map(s => ({ a: s, b: s.replace(/\\n/g, '\n').replace(/\\\\/g, '\\') }))
  .forEach(({a, b}) => console.log(`${toEscaped(a)} --> ${toHex(b)}`))

И на оба замените "\\n" на "\n" и удалите "\\" предшествующих ему символов, попробуйте что-то вроде этого:

const toEscaped = s => s.toSource().match(/"(.*)"/)[0];
const toHex = s => Array.from(s).map((_, i) => s.charCodeAt(i).toString(16).padStart(2, '0')).join('+');
['\n', '\\n', '\\\n', '\\\\n', '\\\\\n']
  .map(s => ({ a: s, b: s.replace(/\\+[n\n]/g, '\n') }))
  .forEach(({a, b}) => console.log(`${toEscaped(a)} --> ${toHex(b)}`))
1 голос
/ 23 апреля 2019

Чтобы удалить все экранированные экранированные символы из исходного текста, это
find: /([^\\]|^)(?:\\\\)+/g replace \1

1 голос
/ 23 апреля 2019

Я думаю, что вы пытаетесь удалить все обратные слеши, начинающиеся с новой строки: str.replace(/\\+\n/g, "\n").

Также вы можете неправильно понимать как работают escape-последовательности :

  • "\\" - одна косая черта

  • "\\n" - одна косая черта, за которой следует буква n

См. Приведенный ниже код для объяснения и обратите внимание, что консольный вывод Stack Overflow перекодирует строку, но если вы проверяете фактические инструменты разработки, лучше и отображаются закодированные символы.

const regex = /\\+\n/g;
// This is "Hello" + [two backslashes] + "nworld"
const evenSlashes = "Hello\\\\nworld";
// This is "Hello" + [two backslashes] + [newline] + "world"
const oddSlashes = "Hello\\\\\nworld";
console.log({
   evenSlashes,
   oddSlashes,
   // Doesn't replace anything because there's no newline on this string
   replacedEvenSlashes: evenSlashes.replace(regex, "\n"),
   // All backslashes before new line are replaced
   replacedOddSlashes: oddSlashes.replace(regex, "\n")
});

enter image description here

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