Генерация имен хостов для ssh-дополнений
May. 10th, 2012 10:19 amПеречитал zshexpn, приемы для работы с файлами.
В zsh можно сконфигурировать стиль для дополнений ssh, который по tab генерирует дополнения для, например, имени хоста. Логично брать их из
Форматы пересказывать не буду, их можно посмотрать по манам.
1. Разбор ~/.ssh/config, будем брать имена из строки
Легенда:
Для perl это будет выглядеть так:
2. Разбор
Легенда:
Теперь можно проверить:
В zsh можно сконфигурировать стиль для дополнений ssh, который по tab генерирует дополнения для, например, имени хоста. Логично брать их из
~/.ssh/config и ~/.ssh/known_hosts.Форматы пересказывать не буду, их можно посмотрать по манам.
1. Разбор ~/.ssh/config, будем брать имена из строки
Host name:${(s. .)${${"${(@M)${(@f)"$(< ~/.ssh/config)"}:#Host[[:space:]][[:space:][:alnum:]-]##}"}#* }}Легенда:
$(< ~/.ssh/config)читаем файл, результат — массив строк, разбитых по пробелам"$(< ~/.ssh/config)", результат — файл, как он есть, без разбивки${(@f)"$(< ~/.ssh/config)}— разбиваем контент по строкам, получаем массив строк${(@M)${(f)"$(< ~/.ssh/config)"}:#Host[[:space:]][[:space:][:alnum:]-]#}— удаляем все, что не попадает под выражениеHost name1( name2 ...):
- В zsh можно использовать классы символов, как
[:space:]класс пробелов и[:alnum:]класс алфавитно-цифровых символов. Символ#после класса обозначает повторение, для pcre это совпадает сHost\s+[\w\s]+ :#удалят из массива совпадающие с паттерном элементы, флагMменяет действие на противоположное, удаляет не совпадающие элементы- Флаг
@показывает, что имеем дело с массивом.
Результат:
# print -l ${"${(M@)${(f)"$(< ~/.ssh/config)"}:#Host[[:space:]][[:alnum:][:space:]-]#}"} Host roof Host arto home Host book Host sut Host ftp2 ...- В zsh можно использовать классы символов, как
${${"${(M@)${(@f)"$(< ~/.ssh/config)"}:#Host[[:space:]][[:alnum:][:space:]-]#}"}##* }— удаляет в каждом элементе массива подстроку сначала и до последнего пробела, оставляя имя хоста:# print -l ${${"${(M@)${(@f)"$(< ~/.ssh/config)"}:#Host[[:space:]][[:alnum:][:space:]-]#}"}##* } roof arto home book sut ftp2 ...(s. .)— делит каждую строку в массиве по пробелу, в результате получим чистый список всех хостов.
Для perl это будет выглядеть так:
perl -lne 'm#Host\s+([\w\s]+)# && print $1' ~/.ssh/config, но порождается один дополнительный процесс.2. Разбор
~/.ssh/known_hosts, хотим брать нормальные имена хостов, ip-адреса и адреса с портом ([host]:port) брать не будем:# print -l ${${${"${(f)"$(< ~/.ssh/known_hosts)"}"%%[ ,]*}:#\[*\]:*}:#[0-9]#.[0-9]#.[0-9]#.[0-9]#}
roof.***.ru
book.***.ru
cube.***.ru
ftp2.***.ru
...Легенда:
$(< ~/.ssh/known_hosts)— читаем весь файл, с разбивкой по пробелам"$(< ~/.ssh/known_hosts)"— весь файл без разбивок${(f)"$(< ~/.ssh/known_hosts)"}— разбиваем контент по строчкам"${(f)"$(< ~/.ssh/known_hosts)"}"— экранируем каждый элемент массива (там могут попадаться спецсимволы, например[и]), результат:# print -l "${(f)"$(< ~/.ssh/known_hosts)"}" roof.***.ru,195.***.130 ssh-dss AAAAB3NzaC1kc3MAAAC... book.***.ru,195.***.246 ssh-rsa AAAAB3NzaC1yc2EAAAA... ...${"${(f)"$(< ~/.ssh/known_hosts)"}"%%[ ,]*}— удаляем теги и ключи, всё после пробела или запятой (%%[ ,]*)${${"${(f)"$(< ~/.ssh/known_hosts)"}"%%[ ,]*}:#\[*\]:*}— удаляем (#:) все элементы массива, совпадающие с паттерном (\[*\]:*, например[www.abc.ru]:22222)${${${"${(f)"$(< ~/.ssh/known_hosts)"}"%%[ ,]*}:#\[*\]:*}:#[0-9]#.[0-9]#.[0-9]#.[0-9]#}— удляем элементы массива (#:) совпадающие с ip-адресом ([0-9]#.[0-9]#.[0-9]#.[0-9]#)
Теперь можно проверить:
# zstyle ':completion:*:(ssh|scp|sftp):*' hosts ${(o)${${"${(f)"$(< ~/.ssh/known_hosts)"}"%%[ ,]*}:#\[*\]:*}:#[0-9]#.[0-9]#.[0-9]#.[0-9]#}
# ssh <TAB>
roof.***.ru book.***.ru cube.***.ru ftp2.***.ru
...
