Когда я прочитал ваш вопрос, моей первой мыслью было $SHLVL
.
Затем я увидел, что вы хотите посчитать уровни vim
в дополнение куровням оболочки.
Простой способ сделать это — определить функцию оболочки:
vim() { ( ((SHLVL++)); command vim "$@");}
Это будет автоматически и незаметно увеличивать SHLVL
каждый раз, когда вы вводите команду vim
.
Вам нужно будет сделать это для каждого варианта vi
/vim
, который вы когда-либо использовали; например,
vi() { ( ((SHLVL++)); command vi "$@");}
view() { ( ((SHLVL++)); command view "$@");}
Внешний набор скобок создает подоболочку,
поэтому ручное изменение значения SHLVL
не загрязняет текущую (родительскую) среду оболочки.
Конечно, ключевое слово command
предотвращает выполнение функций
от вызова самих себя (что привело бы к бесконечному циклу рекурсии).
И, конечно, вы должны поставить эти определения
в ваш .bashrc
или другой файл инициализации оболочки.
Вышеизложенное немного неэффективно. В некоторых оболочках (одной из них является bash), если вы скажете
(cmd1; cmd2; …; cmdn)
, гдеcmdn
— это внешняя исполняемая программа
(т. е. не встроенная команда), оболочка держит лишний процесс лежащим без дела,
просто дождаться завершенияcmdn
.
Это (возможно) не обязательно;
преимущества и недостатки спорны.
Если не жалко прикрутить немного памяти и слот процесса
(и видеть на один процесс оболочки больше, чем вам нужно, когда вы выполняете ps
),
затем выполните вышеуказанное и перейдите к следующему разделу.
То же самое, если вы используете оболочку, которая не поддерживает лишний процесс.
Но если вы хотите избежать дополнительного процесса, первое, что нужно попробовать, это
vim() { ( ((SHLVL++)); exec vim "$@");}
Команда exec
предназначена для предотвращения задержки дополнительного процесса оболочки.
Но есть одна загвоздка.
Обработка SHLVL
в оболочке несколько интуитивно понятна:
При запуске оболочка проверяет, установлен ли SHLVL
.
Если он не установлен (или установлен на значение, отличное от числа),
оболочка устанавливает его равным 1.
Если он установлен (число), оболочка добавляет к нему 1.
Но по этой логике, если вы скажете exec sh
, ваш SHLVL
должен увеличиться.
Но это нежелательно, потому что ваш реальный уровень панциря не увеличился.
Оболочка обрабатывает это,вычитая единицуиз SHLVL
.
когда вы выполняете exec
:
$ echo "$SHLVL"
1
$ set | grep SHLVL
SHLVL=1
$ env | grep SHLVL
SHLVL=1
$ (env | grep SHLVL)
SHLVL=1
$ (env) | grep SHLVL
SHLVL=1
$ (exec env) | grep SHLVL
SHLVL=0
Итак,
vim() { ( ((SHLVL++)); exec vim "$@");}
— промывка; он увеличивает SHLVL
только для того, чтобы снова уменьшить его.
С тем же успехом вы могли бы просто сказать vim
, не пользуясь функцией.
Примечание:
По словам Стефана Шазела (который все знает), некоторые оболочки достаточно умны не, чтобы сделать это, еслиexec
находится в подоболочке.
Чтобы исправить это, вы должны
vim() { ( ((SHLVL+=2)); exec vim "$@");}
Затем я увидел, что вы хотите посчитать уровни vim
независимо отуровней оболочки.
Ну и работает точно такой же трюк (ну, с небольшой модификацией):
vim() { ( ((SHLVL++, VILVL++)); export VILVL; exec vim "$@");}
(и так далее для vi
, view
и т.д.)
Необходимо экспорт
потому что VILVL
не определяется как переменная среды по умолчанию.
Но это не обязательно должно быть частью функции;
вы можете просто сказать exportVILVL
как отдельную команду (в вашем .bashrc
).
И, как обсуждалось выше, если дополнительный процесс оболочки для вас не проблема,
вы можете сделать commandvim
вместо execvim
и оставить только SHLVL
:
vim() { ( ((VILVL++)); command vim "$@");}
Личные предпочтения:
Вы можете переименоватьVILVL
на что-то вродеVIM_LEVEL
. Когда я смотрю на «VILVL
», у меня болят глаза; они не могут сказать, является ли это опечаткой в слове «винил» или неправильно сформированная римская цифра.
Если вы используете оболочку, которая не поддерживает SHLVL
(например, тире),
вы можете реализовать его самостоятельно, если оболочка реализует файл запуска.
Просто сделайте что-нибудь вроде
if [ "$SHELL_LEVEL" = "" ]
then
SHELL_LEVEL=1
else
SHELL_LEVEL=$(expr "$SHELL_LEVEL" + 1)
fi
export SHELL_LEVEL
в своем .profile
или другом файле.
(Возможно, вам не следует использовать имя SHLVL
, так как это вызовет хаос.
если вы когда-нибудь начнете использовать оболочку, которая поддерживает SHLVL
.)
Другие ответы касались этой проблемы встраивания значений переменных среды в приглашение вашей оболочки, так что не буду повторяться, тем более вы говорите, что уже умеете это делать.
Как правило, обрабатывать HTML / XML с помощью регулярных выражений - плохая идея, потому что они недостаточно выразительны для обработки всех угловых случаев. Однако ваш вывод grep предполагает, что мы можем в вашем конкретном случае.
Вот способ обработки вывода, который вы получаете от вашей команды grep, с помощью sed:
sed -e 'N;N;N;N;s/^File-\(.*\):Field1 : \(.*\)<\/title>.*Field2 : .*<span>\(.*\)<\/span *>.*Field3 : .*<span>\(.*\)<\/span *>.*Field4 : .*<span>\(.*\)<\/span *>.*Field5 : .*<span>\(.*\)\s*<\/span *>/\1 | \2 | \3 | \4 | \5 | \6/'
Пояснения:
N; N; N; N;
: это используется для соединения строк пять на пять ( чтобы все поля из файла находились в одной строке) s /
: запускается команда подстановки, первая часть - совпадение, вторая - замена ^ File - \ (. * \):
: соответствует номеру файла Поле1: \ (. * \) <\ / Title>
: соответствует первому полю . * Поле2:. * \ (. * \) <\ / span *>
: соответствует второму / \ 1 | \ 2 | \ 3 / \ 4 | \ 5 | \ 6 /
: это часть замены: каждая группа, ограниченная \ (. * \)
в первой части, фиксируется и может повторно использоваться с помощью специальных переменных \ 1
, \ 2
и т. Д. Результат:
1 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5
2 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5
3 | DATA_FIELD_1 | DATA_FIELD_2 | DATA_FIELD_3 | DATA_FIELD_4 | DATA_FIELD_5
Другой возможный подход заключается в использовании XML-процессора. В данном случае XMLstarlet.
xmlstarlet sel -t -v 'substring-after(//title,":")' \
-m //span -o "|" -v . \
-t -n *.xml
Где:
sel -t
-- выбирает части XML в соответствии со следующим шаблоном-v 'substring-after(//title,":")'
-- это значение title после ":"-m //span -o "|" -v .
-- соответствует span
и печатает "|" и его значение-t -n
-- добавляет новую строку