2015-09-22 4 views
-1

Я изменил имена файлов, поэтому мне нужно сменить имена файлов. Например, я меняю alpha.h на fix_alpha.h. Так что я должен изменить #include "alpha.h" к #include "fix_alpha.h" но есть очень много файлов, чтобы исправить как beta.h к fix_beta.h Я пытался использовать рег ехр, чтобы исправить этоchange include header file с регулярным выражением

grep -rl '*' ./ | xargs sed -i 's/*\.h``/fix_*\.h/g' 

но это не Работа. Как я должен использовать reg exp, чтобы он работал?

+0

'найти. -name '* .h' -print0 | xargs -r0n 1 sed -e's | "alpha.h" | "fix_alpha.h" | g; ' -i' –

+0

Вы пытаетесь изменить имя или содержимое файла? –

+0

Обратите внимание, что ваш вопрос не совсем о C; вы не видите признаков того, что хотите написать программу на C, которая будет делать отображение регулярных выражений (возможно, хорошая вещь - вы будете эмулировать 'sed'). Я вернул его с помощью 'sed' - вы могли бы добавить' grep' и 'xargs', хотя они действительно не нужны. –

ответ

0

Ваша команда grep ищет файлы содержащие * (и большинство из файлов C, вероятно, будет по крайней мере один комментарий, так что все файлы C - источник и заголовок - будут выбраны). Однако вы можете сделать это лучше. Например, если предположить, что имена, которые должны быть сопоставлены, это alpha.h, beta.h, gamma.h и delta.h и что вы обычный программист, который не помещает пробелы или символы новой строки в имена файлов или имена каталогов, тогда вы можете сформировать список интересных файлов с:

grep -rlE '^#include[[:space:]]*"(alpha|beta|gamma|delta)\.h"' . 

Затем для каждого такого файла, вам нужно заменить эти имена заголовков с префиксом fix_. Теперь вы можете решить, имеет ли ваш sed расширенные регулярные выражения. Предполагая, что нет, тогда вы можете создать сценарий sed, чтобы сделать сопоставление для вас. Например, можно создать текстовый файл mapped-headers, содержащий:

alpha.h 
beta.h 
gamma.h 
delta.h 

Теперь сделать что в sed сценарий с (конечно) sed:

sed -e 's/\.h/\\.h/' \ 
    -e 's%.*%s/^#include[[:space:]]*"&"/#include "fix_&"/' \ 
    mapped-headers > script.sed 

Теперь вы можете применить этот сценарий к файлам, содержащим какой-либо из заголовки, которые будут отображаться с помощью:

grep -rlE '^#include[[:space:]]*"(alpha|beta|gamma|delta)\.h"' . | 
xargs sed -i.bak -f script.sed 

(Если вы перезапись файлов на Mac OS X с -i ор вы должны указать суффикс резервного копирования, который может быть присоединен к опции -i, как показано, или в отдельном варианте; если вы не хотите суффикса, но переписываете, вам нужно написать -i '' на Mac. В отличие от этого, если вы используете GNU sed, суффикс резервного копирования является необязательным, но если он присутствует, он должен быть присоединен к опции -i. То, что показано, будет работать на обеих платформах. Не все версии sed поддерживают -i вариант для перезаписи.)

Расширения до 100 заголовков с простым отображением префикса должно быть очевидно, по крайней мере, для части sed сценария. Вы также можете создать скрипт sed и создать сценарий grep; он был бы похож по духу, но проще, чем показанный.

Вы можете написать более удобные регулярные выражения для соответствия отклоняющимся макетам для директив #include. Вы можете разрешить пробелы перед # и после #. Если у вас есть комментарии в операционной части ваших линий #include, у вас есть больше проблем, чем просто сопоставление имен.Этот код не будет обрабатывать:

/* comments? */ # \ 
include /* 
    */ "alpha.h" 

Но никто не имеет права писать такой код в любом случае.

Кроме того, если у вас есть какие-то не вполне систематические переименования делать, вы можете пересмотреть сценарий для обработки, что, изменив файл mapped-headers иметь «старое» и «новое» значение в отдельных столбцах:

alpha.h alphabet.h 
beta.h  veg/carotene.h 
gamma.h hard/radiation.h 
delta.h v-wing.h 
0
find -name '*.h' -exec sed -i 's~alpha.h~fix_alpha.h~' {} \; 

код может содержит /, поэтому здесь используют ~ разделителем

+2

Необходимо также исправлять появление заголовков в исходных файлах; это только ищет файлы заголовков и предполагает, что каждый заголовок включает целевой заголовок. –

+0

Если ни регулярное выражение поиска, ни строка замены не содержат косой черты, вы, безусловно, можете использовать разделитель слэша. Разумеется, выбор разделителя полностью произволен, поэтому '' 'отлично. – tripleee

0

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

sed 's|^\(\s*#\s*include\s.*[*/"]\)\([^/"]*\)\.h\(".*\)$|\1fix_\2.h\3|' 
     \      /\  / \ /
      lines start with   header  everything 
      #include, match   filename after .h 
      until the " or/
      before the header 
      filename 

Пример:

#include "foo.h" 
# include "foo.h" 
    # include "foo.h" 
#include "foo/bar.h" 
#include "foo/bar.h" // something else 

результат

#include "fix_foo.h" 
# include "fix_foo.h" 
    # include "fix_foo.h" 
#include "foo/fix_bar.h" 
#include "foo/fix_bar.h" // something else 
0

Держите это просто:

find . -type f -print | xargs sed -i 's/#include "/&fix_/'