Одной из возможностей получения повторяющихся записей переменных окружения является их рекурсивное определение. Рекурсивное определение имеет место, когда у вас есть в ~/.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
), одним из решений может быть запись этих значений по умолчанию в определении переменной.
Следующее решение работает с популярными 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 .
команда
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
'
На основании указанных правил мы различаем 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