Такое поведение является артефактом библиотеки времени выполнения C и требованием языка программирования C. Другие языки программирования исторически были построены поверх библиотеки времени выполнения C и получили от нее такое поведение. Это справедливо, например, для программ на C++. Глава и стих языковых стандартов C и C++ довольно часто цитируются в Stack Overflow (q.v. ).
В частности, программы, написанные на Python, имеют такое же поведение, и о них довольно часто спрашивают, иногда обвиняя в поведении среду выполнения языка программирования -.
Инструменты для изменения поведения программ, использующих семантику языка по умолчанию (без изменения и перекомпиляции программ )представлены в двух формах :зависимой от языка -(и иногда библиотеки времени выполнения --специальные )инструменты, которые встраиваются в среду выполнения и изменяют буферизацию, а также инструменты, которые выполняют стандартный ввод-вывод в файлы, которые библиотеки среды выполнения определяют как интерактивные устройства. Инструменты последнего класса не зависят от языка -и включают Bernstein ptybandage
.
Несколько примеров вопроса о буферизации:
При использовании Perl-совместимых регулярных выражений (PCRE )добавление +
после \s*
приведет к жадному сопоставлению этих нулевых пробелов, предотвращая сопоставление [^+]
с пробелами. Например. используя grep
с -P
для использования PCRE (параметр grep GNU ), а также -n
для отображения номеров строк:
grep -Pn 'CycleCounter\s*+[^+]' file
Другой PCRE:
grep -Pn 'CycleCounter(?!\s*\+)' file
На этот раз для указания not followed a '+' or some white space and a '+'
используется отрицательный просмотр вперед.
Вы можете использовать sed
для удаления ненужных строк из вывода:
sed '/CycleCounter/!d; /CycleCounter[[:space:]]*+/d; =' file
Удалите все строки, не содержащие CycleCounter, а также удалите все строки, содержащие CycleCounter, за которыми следует любой пробел и «+». =
для печати номеров строк.
Все дело в квантификаторе *
.\s*
-это означает, что совпадений может не быть, а второе выражение [^+] будет соответствовать пробельному символу сразу после слова CycleCounter
.
grep 'CycleCounter\s\+[^+]'
или
grep 'CycleCounter\s*[^+]='
или
grep 'CycleCounter\s*[^+ ]'
Если вы хотите сопоставить CycleCounter
при условии, что это , а не , за которым следует необязательный пробел и +
, вы можете использовать опережающий оператор perl -с отрицательным просмотром:
grep -P 'CycleCounter(?!\s*\+)'
(здесь предполагается grep
реализация, которая поддерживает -P
для perl -, например регулярные выражения ).
Если вы хотите сопоставить CycleCounter
, если за ним следует необязательный пробел и символ, который не является ни +
, ни пробелом:
grep 'CycleCounter[[:space:]]*[^+[:space:]]'
[[:space:]]
является регулярным выражением POSIX, эквивалентным Perl's \s
. Некоторые реализации grep
также поддерживают \s
в своих BRE/ERE как расширение, но не выражения внутри квадратных скобок, где [\s]
требуется POSIX для соответствия либо \
либо s
.
В любом случае, хотя и [[:space:]]
, и \s
будут соответствовать символу новой строки, grep
по умолчанию работает с содержимым одной строки за раз (, не включая разделитель новой строки ), поэтому оба по-прежнему будут совпадать в первой строке:
CycleCounter
+= 12;
, например.
С помощью pcregrep
(, поставляемой с PCRE, библиотекой, которая реализует perl -подобно регулярным выражениям и используется большинством grep
реализаций, поддерживающих -P
параметр ), вы можете сделать:
pcregrep -M '(?s)CycleCounter(?!\s*\+).*?;'
Где -M
включает многострочный режим -, а (?s)
приводит к тому, что .
также соответствует новой строке, а .*?;
используется для проверки полного оператора C до следующего ;
символа. печатается.
Конечно,его все еще можно обмануть такими вещами, как:
CycleCounter // blah ;
+= (c == ';')
+ 3;
Также обратите внимание, что они будут совпадать на MyCycleCounter2 += 3
. Чтобы избежать этого, вы можете добавить операторы границы слов вокруг CycleCounter
. В Perl это \bCycleCounter\b
. Нет эквивалента регулярному выражению POSIX, хотя некоторые реализации grep
также поддерживают \b
или поддерживают \<CycleCounter\>
или [[:<:]]CycleCounter[[:>:]]
в качестве расширения.