Функция включения и выключения сценария оболочки

Для надежного выполнения операции вам потребуются следующие подпрограммы обработки строк:

text_new=${text%%"${match}"*}${word}${text#*"${text%%"${match}"*}"}
#         |------- A -------| |-B--| |------------ C -------------|
  • A— это часть до -совпадения, то есть строка перед началом сопоставления.
    • Он генерируется, когда вы стоите в конце строки, смотрите в начало строки и срываете до последнего появления текста совпадения включительно.
  • B— данные для вставки.
  • C— это часть совпадения после -, то есть строка после окончания совпадения.
    • Он генерируется путем стояния в начале строки, взгляда в конец строки и разрыва до и включая первое обнаружение того, что было результатом Шага. -A.
  • Обратите внимание, что строка совпадения заключена в кавычки, чтобы любые содержащиеся в ней метасимволы не были поняты подпрограммами bashparameter expansion.
  • Должное внимание уделяется возможности совпадения в строке более одного раза. Первая спичка слева заменяется.
  • Также учитывается случай строки с переводом строки.

Сэд

match_esc=$(printf '%s\n' "$match" | sed -e 's|[][^\/.*$]|\\&|g' | sed -e 'H;1h;$!d;g;s/\n/\\n/g')
 word_esc=$(printf '%s\n' "$word"  | sed -e 's|[\&/]|\\&|g;$!s/$/\\/')
printf '%s\n' "$text" | sed -e 'H;1h;$!d;g;'"s/$match_esc/$word_esc&/"''
  • Метод sedявляется более запутанным, так как мы должны убедиться, что все символы, имеющие значение для sedи появляющиеся во входном тексте, должны быть отключены. Еще один уровень сложности заключается в том, что эти символы различны для левой и правой команд s/// команды sed.
  • Следующим шагом является определение этих символов, а затем их заглушение.
  • После этого можно просто запустить текстовые данные через обычный sed s/// материал.
-2
26.07.2019, 10:10
2 ответа

Это означает, что вам придется сохранить текущее состояние активации.

Самый простой способ сделать это — создать файл для одного из состояний (, возможно, для состояния «включено» или «активировано» ), и удалить этот файл при входе в другое состояние (. ] "выключено" или "деактивировано" ).

Создание пустого файла выполняется с помощью touch filename, а проверка существования этого файла выполняется с помощью if [ -e filename ]; then...; fi. Удалите файл с помощью rm filename.

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

Если вы используетеbash:

#!/bin/bash

statefile=$HOME/.script.state

if [ -f "$statefile" ]; then
   . "$statefile"
fi

case $state in
    on) state=off ;;
    *)  state=on
esac

printf 'Current state is "%s"\n' "$state"

declare -p state >"$statefile"

Тестирование:

$ bash script.sh
Current state is "on"
$ bash script.sh
Current state is "off"
$ bash script.sh
Current state is "on"
$ bash script.sh
Current state is "off"

Сценарий сохраняет переменную stateв $HOME/.script.stateс помощью declare -p stateв bashв конце каждого запуска и считывает ее оттуда путем поиска этого файла в начале (, если файл существует ).

В конечном итоге этот файл будет выглядеть так:

declare -- state="off"

, который является результатом declare -p state, если $stateявляется строкой off.


С помощью /bin/shприведенный выше сценарий может быть записан как

#!/bin/bash

statefile=$HOME/.script.state

if [ -f "$statefile" ]; then
    read state <"$statefile"
fi

case $state in
    on) state=off ;;
    *)  state=on
esac

printf 'Current state is "%s"\n' "$state"

printf '%s\n' "$state" >"$statefile"

... просто заменив чтение и запись состояния на readи printf, что позволит сохранить только саму строку состояния в файле состояния.

2
28.01.2020, 05:15

Если вы хотите автоматически инвертировать состояние при каждом запуске, вы также можете воспользоваться числовой операцией «логического отрицания», которая полезна для инвертирования значения. То есть логическое отрицание 0 равно 1, и наоборот.

Оболочки POSIX способны выполнять наиболее распространенные числовые и побитовые операции посредством арифметического расширения и Bash не является коротким , предоставляя также массивы , которые может быть проиндексирован целым числом, таким как 0 или 1 (и более ).

На практике:

(
# our persistent file to save state into
file=./state
# array of two states, "off" is the first so that it will be 0, and "on" will be 1
states=(off on)
# import what's been saved in our state file, if present
[ -f "$file" ] && source "$file"

# within the arithmetic expansion syntax,
# we compute new state as the logical negation (the `!` operator) of the current state
state=$(( !(state) ))
printf 'state=%d\n' $state > "$file"  # save new state to persistent file

# print current state from the array using the numeric state as index 
printf 'currently %s\n' "${states[state]}"
)

В оболочке строго POSIX это немного сложнее, потому что нам нужно обойти отсутствие массивов:

(
file=./state
# here we use a simple string instead of an array
states='off on'
[ -f "$file" ] &&. "$file"  # the `source` command POSIXly is just `.`

state=$(( !(state) ))
printf 'state=%d\n' $state > "$file"

# here we use the `cut` tool to select the piece of string based on numeric state
echo -n 'currently '; printf '%s\n' "$states" | cut -d ' ' -f $((state+1))
)
1
28.01.2020, 05:15

Теги

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