Использование bash для переформатирования «#include» в списке файлов с помощью регулярного выражения

Обратите внимание, что это поведение xsel в еще не выпущенных версиях xsel . Внесено это изменение в 2008 году.

Обычно выделение X содержит текст, не оканчивающийся символами новой строки. Если вы сбросите его как есть, это приведет к отображению незавершенной строки. В старых оболочках, таких как bash , на дисплее отображается:

bash-4.4$ xsel -b
xselbash-4.4$

(здесь при выборе CLIPBOARD, содержащем xsel ). Следующая подсказка добавляется к содержимому выделения.

Современные оболочки, такие как zsh или fish , работают над этим, обнаруживая, когда результат последней команды не заканчивается символом новой строки, и затем дают вам визуальную индикацию.

С zsh :

prompt% xsel -p
xsel%
prompt%

(обратное видео % после xsel указывает на отсутствие новой строки).

С рыбой :

prompt ~> xsel -p
x⏎
prompt ~>

Эти новые xsel сами дают вам визуальную индикацию:

bash-4.4$ xsel -b
xsel
\ No newline at end of selection
bash-4.4$

Теперь это полезно, только если xsel запускается по запросу старого интерактивная оболочка.

В частности, указание «Нет новой строки» нежелательно при использовании как:

selection=$(xsel -b)

(где stdout xsel - канал) или:

xsel -b > selection.txt

(где xsel Стандартный файл - это обычный файл).

Вот почему xsel выводит эту индикацию только тогда, когда stdout идет на tty-устройство.

Итак, где это отображается? Ну, намерение состоит в том, чтобы отобразить его на этом устройстве tty. Если вы запустите его под strace, вы увидите:

$ strace -e write ./xsel -b
write(1, "xsel", 4xsel)                     = 4
write(2, "\n\\ No newline at end of selectio"..., 34
\ No newline at end of selection
) = 34
+++ exited with 0 +++

Что подтверждает источник : он выводится на stderr. И когда stdout не является терминалом:

$ strace -e write ./xsel -b  > /dev/null
write(1, "$ strace -e write ./xsel -b | ca"..., 104) = 104
+++ exited with 0 +++

Он вообще не выводится. Теперь можно утверждать, что выводить на stderr немного глупо, когда намерение состоит в том, чтобы вывести это уведомление на терминал (stderr может быть перенаправлен, например, в файл журнала, как в xsel -b 2> logfile ), но:

  • Обычно, когда stdout является оконечным устройством, stderr тоже.
  • Это означает, что вы можете отключить это уведомление при запуске в терминале с помощью xsel -b 2> / dev / null , что будет более эффективно, чем xsel -b | кот .
  • isatty () вернет истину для последовательного устройства, которое не подключено к терминалу.

1
05.02.2017, 21:54
3 ответа
perl -i.bak -pe '
   if( s!(#include) *(["<])(.*/)?!$1 $2!){  ## if is a include line
        s/(?<=[a-z])(?=[A-Z])/_/g;          ##   insert CamelCase "_"
        tr/A-Z/a-z/ }'   file               ##   lowercase ids
0
27.01.2020, 23:19

Следующий сценарий sed должен это делать:

s/\(#include\) *\([^ ]\+\)/\1 \2/

/^#include "/ {
    s/".*\//"/
    s/"\(.\)/"\l\1/g
    s/\([^A-Z]\)\([A-Z]\)/\1_\l\2/g
    s/_\+/_/g
}

Это можно применить к файлам, запустив:

sed -i.bak -f fix.sed input...

(Предполагается, что приведенный выше сценарий называется fix.sed , а любой { Впоследствии в качестве аргументов можно указать количество файлов {1}}. Удалите .bak , если вы не хотите создавать резервные копии.)

Первое выражение замены sed соответствует #include с последующим , возможно, пустым пробелом ( \ * ), и заменяет этот пробег одним пробелом . Он также переводит остальную часть строки ( [^] \ + ) в нижний регистр (используя \ l ).

Следующие четыре выражения sed, все из которых применяются только к строкам, которые начинаются с #include ", делают следующее:

  1. Удаляют имя пути (все, включая последняя косая черта);

  2. переводит первый символ между кавычками в нижний регистр;

  3. в начале каждого ряда заглавных букв вставляет подчеркивание и переводит первый символ бега в нижний регистр;

  4. сжатие пробежки подчеркивания, возможно, вставленные на предыдущих шагах.

Это несовершенно, но переводит ваш образец ввода должным образом.

4
27.01.2020, 23:19

Вы можете обнаружить, что использование такого инструмента, как astyle форматирует ваш код аккуратно, и делает больше, чем просто исправляет строки #include.

Ваш код хорош, как есть, но если у вас нет пробелов в именах файлов или других странностей, вы можете с тем же успехом использовать find:

astyle --style=allman -A1 --indent=spaces=4  \
   --break-blocks --pad-oper --pad-header --unpad-paren \
   --max-code-length=200 \
   $(find . -name '*.cpp' -print) $(find . -name '*.h' -print)
0
27.01.2020, 23:19

Теги

Похожие вопросы