Скорее всего, они злодеи. Статистика памяти для них не важна, поскольку они используют память ядра.
Я думаю, что нашел простое решение!
cpp -P yourcommentedfile.txt
НЕКОТОРЫЕ ОБНОВЛЕНИЯ:
Цитата пользователя ilkachu (исходный текст из комментариев пользователя):
Я немного поигрался с параметрами gcc: -fpreprocessed отключит большинство директив и расширений макросов (кроме #define и #undef, очевидно). Добавление -dD также оставит определения; и std = c89 можно использовать для игнорирования // комментариев нового стиля. Даже с ними cpp заменяет комментарии пробелами (вместо их удаления) и сворачивает пробелы и пустые строки.
Но я думаю, что это по-прежнему разумное и простое решение для большинства случаев, если вы отключите расширение макроса и другие вещи, я думаю, вы получите хорошие результаты ... - и да, вы можете комбинировать это со сценарием оболочки для улучшения ... и многое другое ...
с sed
:
/\/\*/ {
/\*\// {
s/\/\*.*\*\///g;
b next
};
:loop;
/\*\//! {
N;
b loop
};
/\*\// {
s/\/\*.*\*\//\n/g
}
:next
}
поддерживает все возможные (многострочный комментарий, данные после [или и] до,);
e1/*comment*/
-------------------
e1/*comment*/e2
-------------------
/*comment*/e2
-------------------
e1/*com
ment*/
-------------------
e1/*com
ment*/e2
-------------------
/*com
ment*/e2
-------------------
e1/*com
1
2
ment*/
-------------------
e1/*com
1
2
ment*/e2
-------------------
/*com
1
2
ment*/e2
-------------------
запустить:
{{1 }} $ sed -f command.sed FILENAME
e1
-------------------
e1e2
-------------------
e2
-------------------
e1
-------------------
e1
e2
-------------------
e2
-------------------
e1
-------------------
e1
e2
-------------------
e2
-------------------
Однажды я придумал этот , который мы можем уточнить до:
perl -0777 -pe '
BEGIN{
$bs=qr{(?:\\|\?\?/)};
$lc=qr{(?:$bs\n|$bs\r\n?)}
}
s{
/$lc*\*.*?\*$lc*/
| /$lc*/(?:$lc|[^\r\n])*
| (
"(?:$bs$lc*.|.)*?"
| '\''$lc*(?:$bs$lc*(?:\?\?.|.))?(?:\?\?.|.)*?'\''
| \?\?'\''
| .[^'\''"/?]*
)
}{$1 eq "" ? " " : "$1"}exsg'
, чтобы обработать еще несколько угловых случаев.
Обратите внимание, что если вы удалите комментарий, вы можете изменить значение кода ( 1 - / * комментарий * / - 1
анализируется как 1 - - 1
, а 1–1
(который вы получите, если удалите комментарий) даст вам ошибку). Лучше заменить комментарий пробелом (как мы это делаем здесь), а не полностью удалять его.
Вышеупомянутое должно правильно работать с этим допустимым кодом ANSI C, например, который пытается включить несколько угловых случаев:
#include <stdio.h> int main() { printf("%d %s %c%c%c%c%c %s %s %d\n", 1-/* comment */-1, /\ * comment */ "/* not a comment */", /* multiline comment */ '"' /* comment */ , '"', '\'','"'/* comment */, '\ \ "', /* comment */ "\\ " /* not a comment */ ", "??/" /* not a comment */ ", '??''+'"' /* "comment" */); return 0; }
Что дает следующий результат:
#include <stdio.h> int main() { printf("%d %s %c%c%c%c%c %s %s %d\n", 1- -1, "/* not a comment */", '"' , '"', '\'','"' , '\ \ "', "\\ " /* not a comment */ ", "??/" /* not a comment */ ", '??''+'"' ); return 0; }
Оба печатают один и тот же результат при компиляции и запуске.
Вы можете сравнить с выводом gcc -ansi -E
, чтобы увидеть, что препроцессор сделает с ним.Этот код также является допустимым кодом C99 или C11, однако gcc
по умолчанию отключает поддержку триграфов, поэтому он не будет работать с gcc
, если вы не укажете стандарт, например gcc -std = c99
или gcc -std = c11
или добавьте параметр -trigraphs
).
Он также работает с этим кодом C99 / C11 (не ANSI / C90):
// comment /\ / comment // multiline\ comment "// not a comment"
(сравните с gcc -E
/ gcc -std = c99 -E
/ gcc -std = c11 -E
)
ANSI C не поддерживает форму //
комментария. //
иначе недопустимо в ANSI C, поэтому не будет там отображаться. Один надуманный случай, когда //
может действительно появиться в ANSI C (как отмечено там , и вы можете найти интересную остальную часть обсуждения), когда stringify оператор уже используется.
Это действующий код ANSI C:
#define s(x) #x
s(//not a comment)
И во время обсуждения в 2004 году gcc -ansi -E
действительно расширил его до «// не комментарий»
. Однако сегодня gcc-5.4
возвращает ошибку, поэтому я сомневаюсь, что мы найдем много кода C, использующего такую конструкцию.
Эквивалент GNU sed
может выглядеть примерно так:
lc='([\\%]\n|[\\%]\r\n?)'
sed -zE "
s/_/_u/g;s/!/_b/g;s/</_l/g;s/>/_r/g;s/:/_c/g;s/;/_s/g;s/@/_a/g;s/%/_p/g;
s@\?\?/@%@g;s@/$lc*\*@:&@g;s@\*$lc*/@;&@g
s:/$lc*/:@&:g;s/\?\?'/!/g
s#:/$lc*\*[^;]*;\*$lc*/|@/$lc*/$lc*|(\"([\\\\%]$lc*.|[^\\\\%\"])*\"|'$lc*([\\\\%]$lc*.)?[^\\\\%']*'|[^'\"@;:]+)#<\5>#g
s/<>/ /g;s/!/??'/g;s@%@??/@g;s/[<>@:;]//g
s/_p/%/g;s/_a/@/g;s/_s/;/g;s/_c/:/g;s/_r/>/g;s/_l/</g;s/_b/!/g;s/_u/_/g"
Если ваш GNU sed
слишком стар, чтобы поддерживать -E
или -z
, вы можете заменить первую строку на:
sed -r ":1;\$!{N;b1}
$ cat file | perl -pe 'BEGIN{$/=undef}s!/\*.+?\*/!!sg'
proc print data=sashelp.cars;
run;
data abc;
set xyz;
run;
Удалите пустые строки, если они есть:
$ cat file | perl -pe 'BEGIN{$/=undef}s!/\*.+?\*/\n?!!sg'
Edit - более короткая версия Стефана:
$ cat file | perl -0777 -pe 's!/\*.*?\*/!!sg'
Вот и вы:
sed 's / \ * \ // \ n & / g' test | sed '/\/\*/,/\*\//d'
N.B. Это не работает в OS X, если вы не установите gnu-sed
. Но он работает в дистрибутивах Linux.
sed
работает с одной строкой за раз, но некоторые комментарии на входе несколько строк. Согласно https://unix.stackexchange.com/a/152389/90751 , вы можете сначала использовать tr
, чтобы преобразовать перенос строки в какой-либо другой символ. Затем sed
может обрабатывать ввод как одну строку, и вы снова используете tr
, чтобы восстановить разрывы строк.
tr '\n' '\0' | sed ... | tr '\0' \n'
Я использовал нулевые байты, но вы можете выбрать любой символ, которого нет во входном файле.
*
имеет особое значение в регулярных выражениях, поэтому для соответствия литералу *
потребуется экранирование как \ *
.
. *
жадный - он будет соответствовать максимально длинному тексту, включая дополнительные * /
и / *
. Это означает первый комментарий, последний комментарий и все, что между ними. Чтобы ограничить это, замените . *
более строгим шаблоном: комментарии могут содержать все, что не является «*», а также «*», за которым следует все, кроме «/». Также необходимо учитывать выполнение нескольких *
s:
tr '\n' '\0' | sed -e 's,/\*\([^*]\|\*\+[^*/]\)*\*\+/,,g' | tr '\0' '\n'
Это удалит любые разрывы строк в многострочных комментариях, т.е.
data1 /* multiline
comment */ data2
превратится в
data1 data2
. Если это не то, что нужно, sed
можно указать сохранить один из переносов строки. Это означает выбор заменяющего символа переноса строки, который может быть сопоставлен.
tr '\n' '\f' | sed -e 's,/\*\(\(\f\)\|[^*]\|\*\+[^*/]\)*\*\+/,\2,g' | tr '\f' '\n'
Специальный символ \ f
и использование обратной ссылки, которая, возможно, не соответствует чему-либо, не гарантируют правильную работу во всех реализациях sed
. (Я подтвердил, что он работает на GNU sed 4.07 и 4.2.2.)
с использованием одной строки sed для удаления комментариев:
sed '/\/\*/d;/\*\//d' file
proc print data=sashelp.cars;
run;
data abc;
set xyz;
run;
В руководстве по GNU awk приводится пример с getline , который делает именно то, что я копирую здесь дословно.
# Remove text between /* and */, inclusive
{
while ((start = index($0, "/*")) != 0) {
out = substr($0, 1, start - 1) # leading part of the string
rest = substr($0, start + 2) #... */...
while ((end = index(rest, "*/")) == 0) { # is */ in trailing part?
# get more text
if (getline <= 0) {
print("unexpected EOF or error:", ERRNO) > "/dev/stderr"
exit
}
# build up the line using string concatenation
rest = rest $0
}
rest = substr(rest, end + 2) # remove comment
# build up the output line using string concatenation
$0 = out rest
}
print $0
}
Имейте в виду, что он соединяет mon/*comment*/key
с monkey
. Как упоминает Стефан Шазелас в этом ответе, это может привести к эффективному другому коду, поэтому рассмотрите возможность изменения $0 = out rest
на $0 = out " " rest
.
Сохраните это в файле, например commentRemove.awk
, и выполните его наinputfile
:
awk -f commentRemove.awk inputfile
Почему бы не использовать препроцессор cpp ()?
( sed "s,^\(\s*\)#,\1_:#:_," \
| sed "s,\\\\$,_:%:_," \
| cpp \
| sed "/^\s*#/ d" \
| sed "s,^\(\s*\)_:#:_,\1#," \
| sed "s,_:%:_$,\\\\," \
) < in.c > out.c