Удалять комментарии из файла, игнорируя знаки комментария в кавычках

Одной из возможностей получения повторяющихся записей переменных окружения является их рекурсивное определение. Рекурсивное определение имеет место, когда у вас есть в ~/.bashrcнечто подобное:

export SOME_VARIABLE=$SOME_VARIABLE:/some/paths/

При запуске tmuxпо умолчанию запускается оболочка входа в систему. Вы можете изменить это поведение, установив в ~/.tmux.confпараметр

.

set-option -g default-command bash #or zsh, or whatever

как сказано в этом вопросе . В любом случае tmuxзапускает оболочку, которая, в свою очередь, вызывает~/.bashrc(либо как не -оболочку входа в систему, либо как оболочку входа через~/.profile). Поскольку переменные окружения определяются рекурсивно в файле .bashrc, повторный проход через ~/.bashrcдобавит /some/pathsк этим уже определенным путям. Так что они будут дублироваться.

Многие переменные среды пусты при запуске оболочки. Таким образом, определяя их как

export SOME_VARIABLE=:/some/paths/

не причинит вреда и не позволит tmuxсоздавать дубликаты. Если они начинаются с некоторых значений (, таких как PATH), одним из решений может быть запись этих значений по умолчанию в определении переменной.

0
08.09.2020, 23:58
3 ответа

Решение

Следующее решение работает с популярными sedреализациями, такими как GNU sed, которые поддерживают расширенные регулярные выражения (ERE):

sed -E "s/^(([^#\"'\\]|'[^']*'|\"([^\"\\\\]|\\\\.)*\")*)#.*/\1/" input.txt

Основным преимуществом этого решения является лучшая читаемость, чем у многих других решений.

Примечание.:Переключатель -Eеще не является частью POSIX 2018, но он находится на пути к тому, чтобы стать частью POSIX 2020 . Если вам нужно решение, совместимое с POSIX -2018 -, см. ответ Stéphane Chazelas .

Как это работает

Следующая более длинная версия разбивает указанное выше регулярное выражение на части, которые легче усваиваются:

NON_QUOTED_TEXT="[^#\"'\\]"
SINGLE_QUOTED_STRING="'[^']*'"
DOUBLE_QUOTED_STRING='"([^"\\]|\\.)*"'
REMOVE_COMMENTS="^((${NON_QUOTED_TEXT}|${SINGLE_QUOTED_STRING}|${DOUBLE_QUOTED_STRING})*)#.*"
sed -E "s/${REMOVE_COMMENTS}/\1/" input.txt

Мы используем sedдля поиска текста, соответствующего регулярному выражению, содержащемуся в ${REMOVE_COMMENTS}, и заменяем каждое совпадение содержимым первой группы захвата \1. Эта группа захвата содержит соответствие регулярного выражения между первой открывающей скобкой (и последней закрывающей скобкой ). Эта часть регулярного выражения соответствует любому тексту перед первым знаком комментария (#), который не является частью строки в кавычках.Глядя на это подробно, мы сопоставляем последовательность от 0 до N(*)из следующих вариантов(a|b|c):

  • Текст без -кавычек :символов, кроме #, ", 'и \.
  • Одиночный -текст в кавычках :любое количество(*)символов, кроме(^)кроме ', заключенных в пару одинарных кавычек.
  • Двойной -текст в кавычках :Строка, заключенная в пару двойных кавычек. Строка может содержать любое количество символов, кроме "и \или((a|b))произвольный символ, которому предшествует обратная косая черта(\\.).

Когда вы объединяете части полного решения выше, мы должны помнить, что правила Bash требуют несколько разных кавычек при использовании одинарных и двойных кавычек. Подробнее см. Различия между одинарными и двойными кавычками в Bash .

0
18.03.2021, 23:06

команда

 sed -e '/^#/d' filename| sed "s/# comment$//g"

Питон

#!/usr/bin/python
import re
d=re.compile(r'^#')
r=re.compile(r'#\scomment$')
l=open('p','r')
for  i in l:
    if not re.search(d,i):
        e=re.sub(r,"",i)
        print e.strip()

выход

some text # with a comment
some "quoted text # not a comment"
'# not a comment' "# it's not a comment" '#still not a comment

'

-1
18.03.2021, 23:06

На основании указанных правил мы различаем 5 видов слов:

  • слова в двойных кавычках (они также могут включать экранированные двойные кавычки)"... \"... "

  • слова в одинарных кавычках '...'в них не будет включена одинарная кавычка.

  • слово в кавычках с обратной косой чертой \.практически любой экранированный символ.

  • начальный символ без комментариев[^'#"]

  • то, что осталось, это комментарий.

#! /bin/bash
# whitespace and horizontal whitespace
_ws_=$(printf '\t \nx') 
ws="[${_ws_%?}]" hws="[${_ws_%??}]"

_nac_="[^\"'#]" nac="\($_nac_\)" #not a comment char

_bqw_='[\].'    bqw="\($_bqw_\)" # backslashed word 

_sqw_="'[^']*'" sqw="\($_sqw_\)" # single quoted word 

#double quoted word 
_dqw_='
  "
    \(
      [^\"]* \([\][\]\)* [\]"
    \)*
    [^"]*
  "
'
dqw="\(${_dqw_//$ws/}\)"

sed \
  -e '/#/!b' \
  -e "s/^\(\($sqw*$dqw*$bqw*$nac*\)*\).*/\1/" \
  -e "s/$hws*$//" \
< file

Обратите внимание, что это полностью POS IX

1
18.03.2021, 23:06

Теги

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