2014-07-11 2 views
2

У меня есть большой текстовый файл, который содержит контент в соответствии примере ниже:Удаление определенного символа в любом месте между двумя конкретными строками?

number="+123 123 123" text="This is some text" 
number="+123456" text="This may contain numbers" 
number="+123456 789" text="Numbers here should keep their spaces" 
number="+9 8 7 6 5" text="example 123 123 123" 

То, что я хотел бы, чтобы удалить какой-либо символ пробела между двумя идентифицирующих строк, в этом случае number= и " text=, не касаясь остальной линия. Так что желаемый результат будет:

number="+123123123" text="This is some text" 
number="+123456" text="This may contain numbers" 
number="+123456789" text="Numbers here should keep their spaces" 
number="+98765" text="example 123 123 123" 

Регулярное выражение, как (?<=[0-9])(\s)(?=[0-9]) будет мешать с текстовым полем, что является нежелательным.

Я протестировал несколько вариантов использования чего-то по линиям (?<=address)(\s)(?=date), но это не сработает. Я думаю, что проблема заключается в том, что вы не можете справиться с дополнительными возможными числами между пробелами и маркерами?

Добавление подстановочных матчей в lookbehinds/lookaheads, таких как (?<=address.*)(\s)(?=.*date), кажется недействительным, иначе я сделал это неправильно? Кроме того, создание пробела ленивым с (/s+?), похоже, не помогает мне, но это касается того, где мои знания регулярного выражения действительно рассыпаются :)

В идеале я хотел бы также ограничить между лишними равными и кавычками символы для безопасности , I.e number=" в начале маркера и text=" в качестве маркера конца.

Любые sed/awk или подобные решения также приветствуются, если это проще.

+0

Может ли быть номер в другом месте на линии, которая должна сокращаться, за исключением одного непосредственно после 'number =" + '? Пример' number = "+ 123 123 123" text = "Это текст« number2 = »+ 435 234 132' – Jotne

ответ

3

Используя замену и цикл:

sed ':l s/\(number="[^" \t]*\)\s\s*/\1/g;tl' input 

это один дает:

number="+123123123" text="This is some text" 
number="+123456" text="This may contain numbers" 
number="+123456789" text="Numbers here should keep their spaces" 
number="+98765" text="example 123 123 123" 
+1

+1; Однако 'g' не требуется. Предполагает _GNU_ 'sed'. Для соответствия POSIX используйте 'sed -e ': l' -e 's/\ (number =" [^ "\ t] * \) \ {1, \}/\ 1 /; tl' input'. – mklement0

2

Поиск:[ ](?=[^"]*" text=) ([brackets] вокруг пространства не являются обязательными, они есть для ясности)

Замена: Пустая строка.

В the regex demo см. Подстановки внизу.

Синтаксис командной строки

Я не знаю синтаксис патч в поиск и замену.С Perl (любезно @jaypal и @AvinashRaj):

perl -pe 's/ (?=[^"]*" text=)//g' file 

От perl --help,

-p    assume loop like -n but print line also, like sed 
-e program  one line of program (several -e's allowed, omit programfile) 
+0

Нет, это невозможно благодаря sed. –

+0

@ АвинашРадж Я не знаю, sed. Не могли бы вы объяснить, какая часть невозможна? – zx81

+0

В sed '|' рассматривается как разделитель не как логический оператор. –

4

Использование awk:

awk 'BEGIN{FS=OFS="\""}{gsub(/ /,"",$2)}1' file 
number="+123123123" text="This is some text" 
number="+123456" text="This may contain numbers" 
number="+123456789" text="Numbers here should keep their spaces" 
number="+98765" text="example 123 123 123" 
+1

+1 для подтверждения. – mklement0

+1

Мне нравится 'awk' перед решением' sed', так как он гораздо читабельнее. Некоторые игры в гольф, чтобы сделать его немного короче: 'awk -F \ '' {gsub (/ /," ", $ 2)} 1 'OFS = \" file' – Jotne

1

Другой awk решение:

awk -F ' text="' '{ gsub(/ /, "", $1); print $1 FS $2 }' file 
  • -F text="' расколов каждый входной линии в часть, прежде чем text=" ($1), а часть после ($2) - опция -F устанавливает специальный FS (* Р * IELD * S * eparator) awk переменных в регулярное выражение, что awk использует для разделения каждой строки ввода на поля.
  • gsub(/ /, "", $1) (* g * lobal * sub * stitution) удаляет все пробелы из $1 (часть до text="; заменяет пробелы пустой строкой).
  • print $1 FS $2 печатает вывод: при модифицированных$1 (пробелов удалены), вместе с FS (т.е. text="), вместе с $2 (немодифицированными частями после того, как text=").
1

Примечание: Это дополнение к существующим ответам на сравнить их производительность.

Тестовые среды:

  • OS X 10.9.4.
    • FreeBSD AWK 20070501
    • FreeBSD СЭД (не могу сказать, номер версии)
    • Perl v5.16.2
  • Ubuntu 14.0
    • GNU Awk 4.0.1
    • СЭД (GNU sed) 4.2.2
    • Perl v5.18.2

короткие его:

  • В awk решения быстро.
  • В соответствии с пунктом perl solution.
  • sed solution (accepted answer) является самым медленным.
    • Обратите внимание, что удаление ненужного g варианта делает улучшить положение вещей измеримы, но не меняет общую картину.

На OS X, различия не являются существенными.
На Ubuntu различия между решениями awk и perl малы, но решение sed значительно медленнее.

Примеры номеров, работающих с файлом ввода 100 000 строк 10 раз. Не сравнивайте их напрямую (Ubuntu работает в VM на машине OS X), просто посмотрите на их соотношение. (Любопытно, что awk и perl побежал быстрее в Ubuntu VM):

OS X:

 
# awk (@japyal) 
real 0m3.848s 
user 0m3.773s 
sys 0m0.049s 

# awk (@mklement0) 
real 0m4.011s 
user 0m3.959s 
sys 0m0.045s 

# perl 
real 0m4.382s 
user 0m4.291s 
sys 0m0.063s 

# sed 
real 0m4.867s 
user 0m4.816s 
sys 0m0.044s 

# sed (no `g`) 
real 0m4.510s 
user 0m4.460s 
sys 0m0.044s 

Ubuntu:

 
# awk (@mklement0) 
real 0m1.850s 
user 0m1.788s 
sys 0m0.020s 

# awk (@jaypal) 
real 0m2.055s 
user 0m1.996s 
sys 0m0.012s 

# perl 
real 0m2.349s 
user 0m2.276s 
sys 0m0.024s 

# sed 
real 0m8.278s 
user 0m8.196s 
sys 0m0.016s 

# sed (no `g`) 
real 0m7.580s 
user 0m7.488s 
sys 0m0.028s 
+0

Спасибо за сравнительный анализ. –

+0

@jaypal: Мое удовольствие; У меня была догадка, что решение 'sed' будет медленным из-за цикла. Я считаю, что различия в платформе интересны. – mklement0

+0

Решения sed и perl медленнее из-за использования регулярных выражений, много отслеживания назад (perl) и цикла (sed). Мне больше любопытно различие в awk, хотя оно довольно близко. –

Смежные вопросы