Вот сценарий, который генерирует сценарий , который пытается перехватить все сигналы. Сценарий, который он генерирует ( sigcatcher.sh
), выводит имя пойманного сигнала перед завершением.
#!/bin/sh
# generate a shell function for each and every available signal.
/bin/kill -l | tr ' ' '\n' |
while read signal; do
cat <<END_OF_FUNCTION
handle_$signal () {
echo "Caught $signal"
exit
}
trap 'handle_$signal' $signal
END_OF_FUNCTION
done >sigcatcher.sh
echo 'echo "$$"; sleep 600' >>sigcatcher.sh
В моей системе (OpenBSD) / bin / kill -l
генерирует список доступных сигналов в одной строке, поэтому tr
используется, чтобы разбить его.
Сгенерированный скрипт будет выглядеть примерно так:
handle_HUP () {
echo "Caught HUP"
exit
}
trap 'handle_HUP' HUP
handle_INT () {
echo "Caught INT"
exit
}
trap 'handle_INT' INT
(и т. Д.)
И он будет завершен с помощью
echo "$$"; sleep 600
Он выводит свой PID и находится в спящем режиме в течение 10 минут.
Вы запускаете его так:
$ sh ./sigcatcher.sh >sigcatcher.out
Затем вы закрываете окно и проверяете sigcatcher.out
.
Я не запускаю X Windows, но когда я закрываю панель tmux
, в которой выполняется этот сценарий, я получаю сообщение «Caught HUP» в выходном файле.
Вам нужно экранировать (обратной косой чертой\
)все замененные косые черты /
и все обратные косые черты \
отдельно, поэтому:
$ echo "/tmp/test/folder1/test.txt" | sed 's/\//\\\//g'
\/tmp\/test\/folder1\/test.txt
но это довольно нечитабельно.
Однако sed
позволяет использовать в качестве разделителя практически любой символ вместо /
, это особенно полезно, когда нужно заменить косую черту /
, как в вашем случае, например, используя точку с запятой ;
в качестве разделителя команда стала бы проще:
echo "/tmp/test/folder1/test.txt" | sed 's;/;\\/;g'
Другие случаи:
Если кто-то хочет придерживаться косой черты в качестве разделителя и использовать двойные кавычки, тогда все экранированные обратные косые черты должны быть экранированы еще раз, чтобы сохранить их буквальные значения:
echo "/tmp/test/folder1/test.txt" | sed "s/\//\\\\\//g"
если вообще не нужны кавычки, то нужна еще одна обратная косая черта:
echo "/tmp/test/folder1/test.txt" | sed s/\\//\\\\\\//g
Или, если значение находится в переменной оболочки (bash ):
var=/tmp/test/folder1/test.txt
$ echo "${var//\//\\\/}"
\/tmp\/test\/folder1\/test.txt
Первый //
запуск параметра расширения , говорящий о замене всех совпадений с заменой. Следующий \/
— это экранированный /
для сопоставления, а \\\/
— это экранированный \
, за которым следует экранированный /
в качестве замены.
Окончательное решение будет таким:
$ sed 's:/:\\/:g' <<<"$str"
\/tmp\/test\/folder1\/test.txt
Но объяснить, как туда добраться:
Да, вы пропустили одну обратную косую черту:
$ str='/tmp/test/folder1/test.txt'
$ sed "s/\//\\\\\//g" <<<"$str"
\/tmp\/test\/folder1\/test.txt
Я надеюсь, что один пробел прояснит ситуацию:
$ sed "s/\//\\\\ \//g" <<<"$str"
\ /tmp\ /test\ /folder1\ /test.txt
Но если вы измените разделитель sed на :
(, например):
$ sed "s:\/:\\\\\/:g" <<<"$str"
\/tmp\/test\/folder1\/test.txt
Но это не совсем правильно, так как (теперь не специальный)/
не нуждается в скейпинге:
$ sed "s:/:\\\\/:g" <<<"$str"
\/tmp\/test\/folder1\/test.txt
И, если вы будете использовать одинарные кавычки вместо двойных, оболочка не изменит двойную \\
на единицу, поэтому меньше \
будет правильным:
$ sed 's:/:\\/:g' <<<"$str"
\/tmp\/test\/folder1\/test.txt
Что гораздо чище.