вопрос регулярного выражения - замените все символы новой строки, которым не предшествует табуляция, пробелом - PullRequest
4 голосов
/ 09 августа 2010

Мне нужно обработать блок текста, который может содержать некоторые ложные символы новой строки в середине некоторых полей.Я хочу удалить эти новые строки (заменив их пробелами), не удаляя «действительные» новые строки, которым всегда предшествует \t.

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

"one\ttwo\tbuckle my \nshoe\t\t\n"

станет

"one\ttwo\tbuckle my shoe\t\t\n"

, т. Е. С одним пробелом между 'my' и 'shoe', а не двумя.

EDIT -некоторые уточнения: нежелательные символы новой строки находятся в середине фрагмента обычного текста.Если между словами, где встречается новая строка, есть пробел, я хочу сохранить его.В противном случае я хочу добавить один. Например:

"one\ttwo\tbuckle my \nshoe\t\t\n"
=> "one\ttwo\tbuckle my shoe\t\t\n"

"one\ttwo\tbuckle my\nshoe\t\t\n"
=> "one\ttwo\tbuckle my shoe\t\t\n"

"one\ttwo\tbuckle my \n shoe\t\t\n"
=> "one\ttwo\tbuckle my shoe\t\t\n"

РЕДАКТИРОВАТЬ 2: неуклюжее, но рабочее решение, которое я придумал.Я не очень доволен этим, двойное дублирование кажется нелегким.

>> strings = ["one\ttwo\tbuckle my\nshoe\t\t\n", "one\ttwo\tbuckle my \nshoe\t\t\n", "one\ttwo\tbuckle my \n shoe\t\t\n"]
=> ["one\ttwo\tbuckle my\nshoe\t\t\n", "one\ttwo\tbuckle my \nshoe\t\t\n", "one\ttwo\tbuckle my \n shoe\t\t\n"]
>> strings.collect{|s| s.gsub(/[^\t]\n\s?/){|match| match.gsub(/\s*\n\s*/," ")} }
=> ["one\ttwo\tbuckle my shoe\t\t\n", "one\ttwo\tbuckle my shoe\t\t\n", "one\ttwo\tbuckle my shoe\t\t\n"]

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

Ответы [ 3 ]

2 голосов
/ 09 августа 2010

Нет опции просмотра назад

Вы можете соответствовать:

(\G|[^\t])\n

И заменить обратными ссылками на то, что соответствует группе 1.

Вот фрагмент Ruby (, как видно на ideone.com ):

from = "\none\ttwo\tbuckle my \nshoe\t\t\nx\n\n\t\n\n"
to   = "one\ttwo\tbuckle my shoe\t\t\nx\t\n"

mod  = from.gsub(/(\G|[^\t])\n/, '\1')

puts (mod == to) # true

По сути, мы либо сопоставляем «что-то», которое не является \t, за которым следует \n, и заменяем только частью «что-то» (эффективно сохраняя то, что есть «это», но удаляя \n) или мы можем просто продолжить предыдущее сопоставление, используя \G, чтобы разрешить \n в начале строки или после другого удаленного \n.

Ссылки


Смотри за опцией

Если аромат поддерживает внешний вид, вы также можете выбрать:

(?<!\t)\n

И просто замените на пустую строку.

Ссылки

1 голос
/ 21 августа 2010

С двойным отрицанием ([^\S\t] означает все пробелы, кроме символов табуляции)

def fix(str)
  return str.gsub(/([^\t]|^)[^\S\t]+/, '\1 ')
end

следующие тесты

#! /usr/bin/ruby

require "test/unit"
require "test/unit/ui/console/testrunner"

class MyTestCases < Test::Unit::TestCase
  def test_after_space
    assert_equal fix("one\ttwo\tbuckle my \nshoe\t\t\n"),
                     "one\ttwo\tbuckle my shoe\t\t\n"
  end

  def test_no_whitespace_neighbors
    assert_equal fix("one\ttwo\tbuckle my\nshoe\t\t\n"),
                     "one\ttwo\tbuckle my shoe\t\t\n"
  end

  def test_whitespace_surrounded
    assert_equal fix("one\ttwo\tbuckle my \n shoe\t\t\n"),
                     "one\ttwo\tbuckle my shoe\t\t\n"
  end

  def test_leading_newline
    assert_equal fix("\none\ttwo"),
                     " one\ttwo"
  end
end

Test::Unit::UI::Console::TestRunner.run(MyTestCases)

все проходят:

Loaded suite MyTestCases
Started
....
Finished in 0.000412 seconds.

4 tests, 4 assertions, 0 failures, 0 errors
0 голосов
/ 09 августа 2010
str = str.gsub(/\s*(?<!\t)\n\s*/, " ")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...