Скрытые возможности Bash

Скрипты оболочки часто используются в качестве клея для автоматизации и простых одноразовых задач. Каковы некоторые из ваших любимых "скрытых" возможностей языка оболочки / скриптов Bash?

  • Одна особенность за ответ
  • Приведите пример и краткое описание функции, а не просто ссылку на документацию
  • Пометьте объект, используя жирный заголовок в качестве первой строки

Смотрите также:

43 ответа

вставить последний параметр предыдущей строки

alt-. самая полезная комбинация клавиш, попробуйте и посмотрите, почему-то никто не знает об этом.

нажмите его снова и снова, чтобы выбрать более старые последние параметры.

здорово, когда ты хочешь сделать что-то еще с чем-то, что ты использовал минуту назад.

Если вы хотите сохранить процесс запущенным после выхода из системы:

disown -h <pid>

полезный встроенный bash В отличие от nohup, Вы можете запустить disown на уже запущенном процессе.

Во-первых, остановите свою работу с помощью control-Z, получите pid от ps (или использовать echo $!), используйте bg чтобы отправить его на задний план, затем используйте disown с флагом -h.

Не забудьте оставить фоновую работу, иначе она будет убита при выходе из системы.

Почти все перечисленное в разделе РАСШИРЕНИЕ в руководстве

В частности, расширение параметра:

$ I=foobar
$ echo ${I/oo/aa} #replacement
faabar
$ echo ${I:1:2}   #substring
oo
$ echo ${I%bar}   #trailing substitution
foo
$ echo ${I#foo}   #leading substitution
bar

Мое любимое:

sudo !!

Повторите предыдущую команду с помощью sudo.

Больше волшебных комбинаций клавиш:

  • Ctrl + r начинает "обратный пошаговый поиск" в истории команд. Продолжая вводить текст, он получает самую последнюю команду, содержащую весь введенный вами текст.

  • Tab завершает слово, которое вы уже ввели, если оно однозначно.

  • Вкладка Вкладка перечисляет все дополнения для слова, которое вы уже ввели.

  • Alt + * вставляет все возможные дополнения, что особенно полезно, например, если вы только что ввели потенциально разрушительную команду с подстановочными знаками:

    rm -r source/d*.c Alt + *
    rm -r source/delete_me.c source/do_not_delete_me.c

  • Ctrl + Alt + e выполняет псевдоним, историю и раскрытие оболочки в текущей строке. Другими словами, текущая строка отображается заново, так как она будет обработана оболочкой:

    ls $HOME/tmp Ctrl Alt + E
    ls -N --color=tty -T 0 /home/cramey

Вернуть историю команд и аргументов

Можно выборочно получить доступ к предыдущим командам и аргументам, используя ! оператор. Это очень полезно, когда вы работаете с длинными путями.

Вы можете проверить свои последние команды с history,

Вы можете использовать предыдущие команды с !<n> являющийся n Индекс команды в history, отрицательные числа отсчитываются в обратном порядке от последней команды в истории.

ls -l foo bar
touch foo bar
!-2

Вы можете использовать предыдущие аргументы с !:<n>ноль - команда, >= 1 - аргументы.

ls -l foo
touch !:2
cp !:1 bar

И вы можете сочетать как с !<n>:<m>

touch foo bar
ls -l !:1 !:2
rm !-2:1 !-2:2
!-2

Вы также можете использовать диапазоны аргументов !<n>:<x>-<y>

touch boo far
ls -l !:1-2

Другой ! специальные модификаторы:

  • * для всех аргументов

    ls -l foo bar
    ls !*
    
  • ^ за первый аргумент (!:1 == !^)

  • $ для последнего аргумента

    ls -l foo bar
    cat !$ > /dev/null
    

Мне нравится функция -x, позволяющая увидеть, что происходит в вашем скрипте.

bash -x script.sh 

SECONDS=0; sleep 5 ; echo "that took approximately $SECONDS seconds"

СЕКУНД

При каждом обращении к этому параметру возвращается количество секунд с момента вызова оболочки. Если значение присваивается SECONDS, значением, возвращаемым при последующих ссылках, является количество секунд с момента назначения плюс назначенное значение. Если SECONDS не установлен, он теряет свои специальные свойства, даже если впоследствии он сбрасывается.

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

set completion-ignore-case on

Специальная переменная random:

if [[ $(($RANDOM % 6)) = 0 ]]
    then echo "BANG"
else
    echo "Try again"
fi   

Ctrlx Ctrle

Это загрузит текущую команду в редактор, определенный в переменной VISUAL. Это действительно полезно для длинных команд, таких как перечисленные здесь.

Чтобы использовать vi в качестве редактора:

export VISUAL=vi

Быстрое и грязное исправление опечаток (особенно полезно для длинных команд по медленным соединениям, где использование истории команд и прокрутка ее было бы ужасным):

$ cat /proc/cupinfo
cat: /proc/cupinfo: No such file or directory
$ ^cup^cpu

Также попробуйте !:s/old/new который заменяет старый на новый в предыдущей команде один раз.

Если вы хотите заменить много вхождений, вы можете выполнить глобальную замену с помощью !:gs/old/new,

Вы можете использовать gs а также s команды с любым историческим событием, например

!-2:s/old/new

Заменить old с new (один раз) от второй до последней команды.

Обработка регулярных выражений

Последние выпуски bash имеют соответствие регулярных выражений, так что вы можете сделать:

if [[ "mystring" =~ REGEX ]] ; then  
    echo match
fi

где REGEX - это необработанное регулярное выражение в формате, описанном man re_format.

Совпадения из любых заключенных в скобки частей хранятся в массиве BASH_REMATCH, начиная с элемента 1 (элемент 0 является полностью совпадающей строкой), поэтому вы можете использовать это также для анализа на основе регулярных выражений.

Вот два из моих любимых:

Чтобы проверить синтаксис без реального выполнения скрипта, используйте:

bash -n script.sh

Вернитесь к последнему каталогу (да, я знаю pushd и popd, но это быстрее)

cd -

Использование логических операторов Infix

Рассмотрим простой, если:

if [ 2 -lt 3 ]
    then echo "Numbers are still good!"
fi

Это выглядит ужасно. Не очень современный. Если вы используете двойные скобки вокруг вашего логического выражения, вы можете использовать обычные логические операторы!

if [[ 2 < 3 ]]
    then echo "Numbers are still good!"
fi

Волшебные комбинации клавиш от bash man страницы:

  • Ctrl + a и Ctrl + e перемещают курсор в начало и конец текущей строки соответственно.

  • Ctrl + t и Alt + t транспонируют символ и слово перед курсором с текущим, затем перемещают курсор вперед.

  • Alt + u и Alt + l преобразуют текущее слово (от курсора до конца) в верхний и нижний регистр.

    Подсказка: нажмите Alt + -, а затем любую из этих команд, чтобы преобразовать начало текущего слова.


бонус man чаевые:

  • Во время просмотра man страниц, используйте / для поиска текста на страницах. Используйте n, чтобы перейти к следующему матчу или N для предыдущего.

  • Ускорить поиск определенной команды или подраздела в man страницы, используя преимущества их форматирования:

    o Вместо того, чтобы вводить / расширение истории, чтобы найти этот раздел, попробуйте / ^ history, используя каретку (^) найти только те строки, которые начинаются с "истории".

    o Попробуйте / прочитайте с несколькими начальными пробелами, чтобы найти эту встроенную команду. Встроенные всегда имеют отступ в man страницы.

Выполнение команды перед отображением приглашения bash

Задайте команду в переменной env "PROMPT_COMMAND", и она будет запускаться автоматически перед каждым приглашением. Пример:

[lsc@home]$ export PROMPT_COMMAND="date"
Fri Jun  5 15:19:18 BST 2009
[lsc@home]$ ls
file_a  file_b  file_c
Fri Jun  5 15:19:19 BST 2009
[lsc@home]$ ls

Для дураков следующего апреля добавьте "export PROMPT_COMMAND=cd" в чей-то.bashrc, затем откиньтесь на спинку кресла и наблюдайте, как развивается путаница.

Массивы:

#!/bin/bash

array[0]="a string"
array[1]="a string with spaces and \"quotation\" marks in it"
array[2]="a string with spaces, \"quotation marks\" and (parenthesis) in it"

echo "There are ${#array[*]} elements in the array."
for n in "${array[@]}"; do
    echo "element = >>${n}<<"
done

Более подробную информацию о массивах (и других продвинутых сценариях bash) можно найти в Расширенном руководстве по Bash-Scripting.

Вы можете игнорировать определенные файлы при заполнении вкладки, установив FIGNORE переменная.

Например, если у вас есть репозиторий subverion, и вы хотите легче ориентироваться, выполните

export FIGNORE=".svn"

Теперь вы можете cd без блокировки .svn каталоги.

расстегивать

CS- Control Shift Минус Отмена действий при наборе текста.

Убить / янки

Любая операция удаления Cw (удалить предыдущее слово), Ck (удалить до конца строки), Cu (удалить до начала строки) и т. Д.... копирует удаленный текст в список уничтожений, последнее удаление можно вставить с помощью: Cy и циклически проходить (и вставлять из) кольцо удаленных элементов с помощью Alt-y

export TMOUT=$((15*60))

Завершите работу bash после 15 минут простоя, для отключения установите значение 0. Я обычно помещаю это в ~/.bashrc на моих учетных записях root. Это удобно при администрировании ваших ящиков, и вы можете забыть выйти из системы, прежде чем уходить из терминала.

Расширение скобки

Стандартное расширение с {x,y,z}:

$ echo foo{bar,baz,blam}
foobar foobaz fooblam
$ cp program.py{,.bak}  # very useful with cp and mv

Расширение последовательности с помощью {x..y}:

$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo {a..f}{0..3}
a0 a1 a2 a3 b0 b1 b2 b3 c0 c1 c2 c3 d0 d1 d2 d3 e0 e1 e2 e3 f0 f1 f2 f3

Используя арифметику:

if [[ $((2+1)) = $((1+2)) ]]
    then echo "still ok"
fi

Усечение содержимого файла (обнуление файла)

> file

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

Еще один маленький:Alt+#

закомментирует текущую строку и переместит ее в буфер истории.

Поэтому, когда вы собираете командную строку и вам нужно ввести временную команду, например, для поиска файла, вы просто нажимаете alt+#, вводите другую команду, заходите в историю, раскомментируете и продолжаете.

Недавно я прочитал " Программирование Csh вредно", в котором содержится этот поразительный драгоценный камень:

Рассмотрим трубопровод:

A | B | C

Вы хотите знать статус C, ну, это легко: он находится в $? Или $status в csh. Но если ты хочешь этого от А, тебе не повезло - если ты в csh, то есть. В оболочке Bourne вы можете получить его, хотя сделать это немного сложно. Вот что мне нужно было сделать, когда я запустил dd stderr в трубу grep -v, чтобы избавиться от шума ввода / вывода записей, но должен был вернуть состояние выхода dd, а не grep:

device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
    egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;

Брекеты вместо do а также done в течение цикла

For тело цикла обычно находится в do...done (просто пример):

for f in *;
do
    ls "$f";
done

Но мы можем использовать стиль C, используя фигурные скобки:

for f in *; {
    ls "$f";
}

Я думаю, что это выглядит лучше, чем do...done и я предпочитаю этот. Я еще не нашел этого ни в одной документации Bash, так что это действительно скрытая функция.

Не совсем особенность, а скорее направление: я нашел много "скрытых возможностей", секретов и различных полезностей bash на http://www.commandlinefu.com/. Многие из самых рейтинговых ответов на эти ответы я узнал на этом сайте:)

Легко перемещаться между несколькими каталогами

Не скрытая функция, но гораздо более гибкая, чем pushd, которая требует стековой навигации.

a() { alias $1=cd\ $PWD; }

cd где-то и введите a 1, Позже просто печатать 1 вернется в этот каталог.

Эти свойства являются еще одним из моих любимых.

export HISTCONTROL=erasedups
export HISTSIZE=1000

Первый гарантирует, что bash не будет регистрировать команды более одного раза, будет действительно улучшен historyПолезность Другой расширяет размер истории до 1000 со значения по умолчанию 100. На самом деле я установил это значение на 10000 на своих машинах.

Другие вопросы по тегам