обработка текста: извлеките части файла и запишите их в одну строку

Когда я прочитал ваш вопрос, моей первой мыслью было $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.)


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

1
30.03.2017, 00:20
2 ответа

Как правило, обрабатывать 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
0
28.01.2020, 00:58

Другой возможный подход заключается в использовании 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 -- добавляет новую строку
1
28.01.2020, 00:58

Теги

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