2010-05-14 2 views
2

Я пытаюсь использовать sed для замены пробелов внутри строки. Например, если линия:Удаление пробелов SED в строке

var test = 'Some test text here.'; 

Я хочу получить:

var test = 'Sometesttexthere.'; 

Я попытался с помощью (\x27 спички '):

sed 's|\x27\([^\x27[:space:]]*\)[[:space:]]|\x27\1|g 

, но это просто дает

var test = 'Sometest text here.'; 

Любые идеи?

ответ

1

Это гораздо более сложный сценарий sed, но он работает без цикла. Вы знаете, просто ради разнообразия:

sed 'h;s/[^\x27]*\x27\(.*\)/\n\x27\1/;s/ //g;x;s/\([^\x27]*\).*/\1/;G;s/\n//g' 

Это делает копию строки, расщепляет один (который станет второй половиной) на первой одинарной кавычки отбрасывая первую половину, заменяет все пробелы в вторая половина, свопирует копии, разделяет вторую, отбрасывая вторую половину, объединяет их вместе и удаляет новые строки, используемые для расщепления, и добавляет команду G.

Edit:

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

sed '/.*=.*\x27.*\x27.*/ {h;s/[^\x27]*\x27\(.*\)/\n\x27\1/;s/ //g;x;s/\([^\x27]*\).*/\1/;G;s/\n//g}' 

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

+0

Хорошее решение. Кажется, что O (n) вместо моего O (n^2) [Shlemiel the Painter solution] (http://en.wikipedia.org/wiki/Schlemiel_the_Painter%27s_algorithm), но этот факт, вероятно, не имеет отношения к входные длины под рукой. –

+0

Ваши навыки sed (regex) очень заметно превосходят мои. Очень хорошее решение. Одна вещь, я думаю, я должен был упомянуть, что не каждая строка имеет. Ваше решение отлично работает для линий, которые делают. Тем, у кого нет, в конечном итоге все же скопировано. Например, строка с var x = 2; закончится как var x = 2; var x = 2; – blazeprogrammer

+0

Для всех, кому это интересно, это решение намного быстрее, чем принятое решение, причем основное отличие заключается в том, что он работает не так, как нужно (моя ошибка, а не ответчик). В моем тестовом файле это решение занимает 0,6 с, а принятое решение занимает 19,3 с. – blazeprogrammer

0

Ваша командная строка имеет две проблемы:

  • Во-первых, это отсутствие \ после [^.

  • Во-вторых, хотя вы используете модификатор g, удаляется только первое место. Зачем? Поскольку этот модификатор приводит к замене последовательных совпадений в той же строке. Он делает не повторное сканирование всей строки с самого начала. Но это требуется здесь, потому что ваш матч привязан к начальному ' строкового литерала.

Очевидный способ решения этой проблемы заключается в использовании цикла, реализованный с помощью условного перехода (прыжка с tLabel к :Label; t скачки, если по крайней мере один s согласованного с момента последнего теста с t).

Это самый простой с SED сценарий (и вам не придется бежать '), например, так:

:a 
s|'\([^'[:space:]]*\)[[:space:]]|'\1| 
ta 

Но это можно сделать один командной строки. Точный синтаксис может зависеть от вашего SED вкуса, шахтный (супер-СЭД на Windows) он вызывается следующим образом:

sed -e ":a" -e "s|\x27\([^\x27[:space:]]*\)[[:space:]]|\x27\1|;ta" 

Вам понадобится два отдельных выражений сценария, так как метка :a простирается до конца выражения ,

+0

Использование GNU 'sed', точка с запятой заканчивается ярлыком. –

+0

@ Dennis: Действительно, теперь, когда я пытался, он также работает с супер-sed. Похоже, что раньше я использовал другую версию sed, которая не поддерживала ее, и никогда не потрудилась снова проверить. –

+0

Это решение работает точно по мере необходимости. Как вы отметили в своем комментарии выше, это не самый эффективный. Это актуально для моих входных длин, но оно работает достаточно хорошо для моего приложения. Благодарю. – blazeprogrammer

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