Как сопоставить) \ n {используя sed? - PullRequest
0 голосов
/ 16 января 2019

Мне нужно написать скрипт оболочки, который будет вводить строку в мои файлы .c после довольно сложного шаблона для соответствия.

Узор: )\n{,

без пробелов / пробелов между \n и {. То есть я хочу сопоставить с {, расположенным в первом столбце моего файла (это для ТОЛЬКО совпадения с )\n{ следующими объявлениями функций в C, а не теми, которые следуют за циклами или условиями).

void some_function_declaration(char var1, char var2) {

Я прочитал руководства, форумы и до сих пор не могу понять, как правильно написать шаблон или найти соответствующее регулярное выражение. Соответствующий вывод будет:

void some_function_declaration(char var1, char var2) { time_exe(__func__, cl(clock())); rest of the function...

Далее следует то, что я придумала до сих пор и не работает.

Попробуйте 1

sed -i '' '/)$\n{/a time_exe(__func__, cl(clock()));' >> list_func2.c

Попробуйте 2

sed -i '' '/)\n{ /a time_exe(__func__, cl(clock()));' >> list_func2.c

Попробуйте 3

sed -i '' '/)/\n{/a time_exe(__func__, cl(clock()));' >> list_func2.c

Я был бы очень рад услышать ваши рекомендации по этому вопросу.

Ответы [ 4 ]

0 голосов
/ 16 января 2019

Perl может быть хорош для этого:

$ cat file.c
void some_function_declaration(char var1, char var2)
{
    if (a)
    { b; }
}
void func2()
{
    //
}
$ perl -0777 -pe 's {\)\n\{} {$& some other stuff;\n}g' file.c
void some_function_declaration(char var1, char var2)
{ some other stuff;

    if (a)
    { b; }
}
void func2()
{ some other stuff;

    //
}

То же предостережение, что и Ответ Аарона из-за чтения всего файла в память.

0 голосов
/ 16 января 2019

Я согласен с @Aaron, но если вы все еще хотите точно sed, посмотрите на это:

$  cat /tmp/del.txt
void some_function_declaration(char var1, char var2)
{
  ...
}
void enother_function_declaration(char var1, char var2)
{
  ...
}

И, применяя sed:

$ cat /tmp/del.txt | sed ':a;N;$!ba;s/)\n{/)\{\ntime_exe(__func__, cl(clock()));/g'
void some_function_declaration(char var1, char var2){
time_exe(__func__, cl(clock()));
  ...
}
void enother_function_declaration(char var1, char var2){
time_exe(__func__, cl(clock()));
  ...
}

Я думаю, это выглядит так, как ты хотел

UPD

Позвольте мне объяснить ..

Более кросс-платформенный синтаксис:

sed -e ':a' -e 'N' -e'$!ba' -e 's/)\n{/)\n{ ... ;/g'

, где

  • ':a' - создает метку ветки (с именем a), которую можно вернуть позже
  • 'N' - добавляет следующую строку к текущей (с \n между)
  • '$!ba' - переход к метке a, если следующая строка является последней строкой
  • 's/)\n{/)\n{ ... ;/g' - делает глобальное замещение в одной строке, состоящей из всех строк и \n s
0 голосов
/ 16 января 2019

Это может сработать для вас (GNU sed):

sed ':a;/)$/!b;n;/^{/!ba;c{ time_exe(__func__, cl(clock()));' file

Если текущая строка не заканчивается на ), прекратите дальнейшую обработку с помощью sed. В противном случае выведите текущую строку и прочитайте следующую. Если эта строка не начинается с проверки { с начала, в противном случае измените ее на желаемый формат.

Можно также добавить или вставить нужный формат, см. Ниже:

sed ':a;/)$/!b;n;/^{/!ba;a{ time_exe(__func__, cl(clock()));' file

Или,

sed ':a;/)$/!b;n;s/^{/& time_exe(__func__, cl(clock()));/;Ta' file
0 голосов
/ 16 января 2019

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

Если вы настаиваете на использовании sed и используете GNU sed, выоднако можно использовать опцию -z / --null-data, которая будет считывать весь файл за один проход (чтение записей, разделенных NUL-байтами, а не записями, разделенными строкой) и позволит вам использовать шаблон )\n{, как и следовало ожидать:

$ { echo "line1)"; echo "{line2"; } | sed -z 's/)\n{/X/g'
line1Xline2

Поскольку для этого требуется загрузка всего файла в память, ожидайте ужасных результатов при работе с огромными файлами.


Если вам нравится неуправляемый бред, вы можете решить эту проблему с помощью sedМенее известные команды P, t и D:

sed '/)$/{N;s/)\n{/) {\n\ttime_exe(__func__, cl(clock()));/;t;P;D}'

Попробуйте здесь!

Это работает путем загрузки дополнительной строки впространство образца (N), когда встречается строка, оканчивающаяся на ), при попытке замены на шаблон с двумя линиями, печати (P) и удалении (D) первой строки из пространства образцаесли шаблон не соответствует (в противном случае t переходит к следующей итерации), оставляя вторую строку в пространстве шаблона для использования в качестве первой строки следующей итерации.

Использование /first line pattern/{N;s/whole pattern/replacement/} часто достаточно хорошо, но может привести к сбоюпоскольку N будет использовать строку, с которой вы не будете проверять шаблон первой линии.Это иллюстрируется здесь .

...