Прокомментируйте несколько строк в файле, используя sed

Я работаю на MAC OSX. Я пишу сценарий оболочки, чтобы добавить префикс «//» ко всем сообщениям журнала в файле. Я написал следующий sed-скрипт:

    sed -i '' "s|"log+*"|"//log"|g" filename

Сценарий работает нормально, когда сообщение журнала состоит из одной строки. Но если в журнале несколько строк, он не работает. например:

    log("hi
         how are
         you");

вывод для этого получается:

    //log("hi
           how are
           you");

Но я хочу, чтобы результат был:

    //log("hi
    //     how are
    //     you");

Поскольку я мало использовал sed, я не знаю, как это сделать. Итак, можно ли это сделать с помощью sed. Если да, то как?

Спасибо


person rsKRISH    schedule 04.06.2015    source источник
comment
Вы ограничены в использовании sed или доступны некоторые другие инструменты, такие как awk?   -  person nu11p01n73R    schedule 04.06.2015
comment
@ nu11p01n73R В настоящее время я использую sed, но если это можно сделать с помощью любого другого инструмента, я могу его использовать.   -  person rsKRISH    schedule 04.06.2015


Ответы (3)


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

sed "/^\s*log.*;$/ s|^|//|; /^\s*log/, /);$/ s|^|//|" input

Что он делает?

  • /^\s*log.*;$/ s|^|//| Если строка начинается с log и заканчивается на ;, замените начало, ^ на //

  • /\s*^log/, /);$/ s|^|//|"

    • /^log/, /);$/ This is an address range. For all lines within this range, the substitution is performed. The range of lines start from the first regex match to the end match.

Тест

$ cat input
log("hi
         how are
         you");

this will also be not commented; 

log ("test);

this is not commented;

$  sed "/^\s*log.*;$/ s|^|//|; /^\s*log/, /);$/ s|^|//|" input
//log("hi
//         how are
//         you");

this will also be not commented; 

//log ("test);

this is not commented;
person nu11p01n73R    schedule 04.06.2015
comment
В зависимости от отступа команд журнала, /^\s*log.../ для каждого совпадения с шаблоном может оказаться полезной настройкой. - person cmbuckley; 04.06.2015
comment
@cmbuckley Это делает его более совершенным. Спасибо за совет. Обновлено в ответ :) - person nu11p01n73R; 04.06.2015
comment
@ nu11p01n73R Спасибо .. :) - person rsKRISH; 04.06.2015
comment
@ nu11p01n73R nu11p01n73R Я попробовал ваше предложение, но оно по-прежнему не работает, если перед строкой есть пробелы. Это работает на вашем конце? - person rsKRISH; 04.06.2015
comment
Для MAC OS нам нужно использовать [[sapce]] для сопоставления пробелов. sed /^[[:space:]]*log.*;$/ s|^|//|; /^[[:space:]]*log/, /);$/ s|^|//| работает на Mac OS. Спасибо за вашу помощь. - person rsKRISH; 04.06.2015

Вы можете использовать sed:

sed '/log/{:a;s/.*/\\\\\0/;/);[[:space:]]*$/!{n;ba}}' input.txt
  • /log(/ ищет строку, содержащую открывающий термин log(.
  • { открывает блок кода
  • :a определяет метку с именем a
  • s/.*/\\\\\0/ добавляет \\ перед строкой
  • /);[[:space:]]*$ ищет закрывающий ); с последующим необязательным пробелом в конце строки
  • !{n;ba} выполняется, если шаблон не найден. n получает новую строку. ba разветвляется обратно на a.
person hek2mgl    schedule 04.06.2015
comment
Выдает ошибку: sed: 1: /log/{:a;s/.*/\\\\\0/;/ ...: неожиданный EOF (ожидание }'s) . - person rsKRISH; 04.06.2015
comment
Убедитесь, что вы правильно скопировали и вставили команду. Он работает. - person hek2mgl; 04.06.2015

Конечно, это не может работать. Вы выполняете sed для слова «журнал», что означает, что если этого слова нет в начале каждой строки, вы ничего не замените.

Можете ли вы подтвердить, что это работает, если вы добавите слово «журнал» в начале первых трех строк?

Если да, то решение будет состоять в том, чтобы сохранить ту же команду, но удалить слово «журнал». Может быть, что-то вроде sed -i '' "s|"+*"|"//"|g" filename (я не знаком с sed для Mac OS X, поэтому не буду здесь ничего утверждать).

person Shruikan    schedule 04.06.2015