Я хотел бы сократить один из своих сценариев, и я получил na идею, но я не знаю, как сделать это. Имейте часть кода как это:
COMMAND="find /etc -type "
case $1:
"directory") $COMMAND d
;;
esac
Конечно, это - короткая версия :) И теперь я хочу смочь сократить его, не towrite, что $COMMAND везде, таким образом, я хотел бы иметь что-то вроде этого:
$COMMAND <the case statement return value>
но я не хочу использовать переменную для хранения результата случая.
Спасибо :) Надеюсь, что Вы поняли то, что я хочу :D
РЕДАКТИРОВАНИЕ 1: Его возможное, чтобы создать функцию и передать параметр находки как 1$, как указано Serg. Теперь, ЕСЛИ я хотел сделать это только без функции, я уверен, что существует путь :D Не как Serg не решил его, мне просто любопытно :D
Существует несколько возможных способов упростить код. Ниже решения, заказанные объемом кода:
printf
и замена параметра (никакая проверка ошибок)xargs
и замена параметра (никакая проверка ошибок)find
и параметр substition только (никакая проверка ошибок)printf
и решение для замены параметра
Немного известного качества printf
функция - это, если Вы звоните printf "%c" someString
, это распечатает только первый символ той строки. Таким образом мы можем избегать использования оператора выбора с расширением параметра и printf
как так:
xieerqi:$ cat someScript.sh
#!/bin/bash
find /etc -type $(printf "%c" $1 )
теперь выполнитесь:
xieerqi:$ sudo ./someScript.sh directory | head
[sudo] password for xieerqi:
/etc
/etc/logrotate.d
/etc/apm
/etc/apm/event.d
/etc/apm/scripts.d
/etc/apm/resume.d
/etc/apm/suspend.d
/etc/speech-dispatcher
/etc/speech-dispatcher/modules
/etc/speech-dispatcher/clients
Ограничение здесь - то, что мы разветвляем процесс для вызова printf
, которого функциональное решение избегает - функциональная и выбирающая структура является всеми собственными инструментами удара.
xargs
и замена параметра
Используя замену параметра удара мы можем обрубить подстроку от переменной (например, ${VAR:0:3}
дает сначала 3 символа VAR
); в этом случае мы хотим первый символ для типа directory
или file
. Затем мы можем использовать xargs
передать это как параметр к find
echo ${1:0:1} | xargs -I {} find /etc -type {}
find
страница справочника упоминает это для -type
флаг на Солярисе там является чем-то известным как дверной файл, который представлен прописной буквой D
, но так как мы находимся на Linux, мы можем сказать, что это - ограничение, которое разумно для игнорирования.
Однако существует другая опасность в этом коде - если пользователь входит flower
как $1
параметр, это все еще собирается искать -type f
, потому что мы берем первый символ любой строки …, Другими словами, нет никакой проверки ошибок.
find
с расширением параметра
Используя расширение параметра еще больше, мы можем сделать это:
find /etc -type ${1:0:1}
В основном, острота с find
команда и подстрока $1
переменная. Кроме того, никакая проверка ошибок.
Провалитесь выбирающая структура
Большой проблемой с последними тремя методами является проверка ошибок. Они хороши, когда Вы доверяете пользователю, чтобы не быть макетом или просто написанием кода для себя. Теперь, в Java возможно записать a switch
оператор, который выполнит ту же команду для нескольких случаев, если Вы просто опустите break
команда. В bash
это может быть сделано также с ;&
разделитель. Кавычка от man bash
Используя
;&
вместо;;
выполнение причин, чтобы продолжить список, связанный со следующим набором шаблонов.
Все, что мы должны сделать, протестировать на типы, как "каталог", "файл", "блок" и так далее, и затем использовать замену параметра для обрубания первого символа. Как так
#!/bin/bash
case "$1" in
"directory") ;&
"file");&
"block") find /etc -type ${1:0:1} ;;
*) exit 1 ;;
esac
5. Протестируйте логику, xargs, и замену параметра
Basic idea here is that we're sending $1 variable through pipe to `xargs`, which in turn substitutes it into test (again square brackets). `xargs` in turn builds the actual command that runs by replacing `{}` with whatever was passed to `xargs`. As for test command, it's simple or statement, `EXPRESSION -o EXPRESSION ` , where we test if string $1 is equal to either "file" or "directory string"
echo "$1" | xargs -I {} [ "{}" = "file" -o "{}" = "directory" ] \
&& find /etc -type ${1:0:1}
`xargs` is really useful when you need to process multiple argumens with the same command. Considering that in this case we only have one argument that needs to be processed with the same command , this can be simplified to
[ "$1" = "file" -o "$1" = "directory" ] && find /etc -type ${1:0:1}
Of course the big limitation is that if you test for more than one type, you need longer `[ EXPR1 -o EXPR2 ]` structure with multiple `-o` parts.
Функциональное решение
find
команда может быть помещена в функцию, которая затем может быть вызвана с позиционными параметрами.
Например:
function findStuff
{
find /etc -type "$1"
}
Вот маленькая демонстрация. Заметьте, что я использую sudo
потому что для большого количества файлов в /etc
у обычных пользователей нет полномочий чтения
xieerqi:$ sudo ./someScript.sh directory | head
[sudo] password for xieerqi:
/etc
/etc/logrotate.d
/etc/apm
/etc/apm/event.d
/etc/apm/scripts.d
/etc/apm/resume.d
/etc/apm/suspend.d
/etc/speech-dispatcher
/etc/speech-dispatcher/modules
/etc/speech-dispatcher/clients
xieerqi:$ sudo ./someScript.sh file | head
[sudo] password for xieerqi:
/etc/hosts.deny
/etc/logrotate.d/speech-dispatcher
/etc/logrotate.d/pm-utils
/etc/logrotate.d/rsyslog
/etc/logrotate.d/yate
/etc/logrotate.d/apport
/etc/logrotate.d/apt
/etc/logrotate.d/consolekit
/etc/logrotate.d/fail2ban
/etc/logrotate.d/cups-daemon
xieerqi:$ cat someScript.sh
#!/bin/bash
function findStuff
{
find /etc -type "$1"
}
case "$1" in
"directory")findStuff d ;;
"file") findStuff f;;
esac
Массив, для цикла, тест и &&
Основная идея здесь - соответствует входу пользователя против списка и, если подобрано делает что-то. Мы создаем массив объектов, чтобы проверить на, иметь условие испытания (квадратные скобки по тому, как псевдоним к test
команда), и просто выполненный цикл для тестирования переменной за 1$. &&
оператор позволяет выполнять команду если и только если, слева от чего &&
было успешно. Таким образом, если мы нашли строку, это находится в массиве, мы выполняемся, находят команду. $ {1:0:1} был обсужден в предыдущих примерах - расширение параметра, которое прерывает - от первого символа от нашего подобранного типа. Таким образом, это решение имеет проверку ошибок и всех из кода, упакованного во всего 3 строки (4, если Вы включаете #!
строка).
#!/bin/bash
array=("file" "directory" "block");
for TYPE in "${array[@]}"; do
[ "$1" = "$TYPE" ] && find /etc/ -type ${1:0:1};
done
Поместите его в функцию:
MyFind () {
COMMAND="find /etc -type "
case $1:
"directory") $COMMAND d
;;
esac
}
Теперь Вы можете всегда использовать его в качестве MyFind $TYPE
, Вы можете также поместить только заявление случая в функцию
FType () {
case $1 in
"directory") echo d;;
"file") echo f;;
esac
}
COMMAND="find /etc -type "
$COMMAND $(FType $TYPE)
[[ "$1" == "directory" ]] && find /etc -type d
Другой подход:
declare -A foo # associative array
foo["directory"]="d"
foo["file"]="f"
foo["link"]="l"
find /etc -type ${foo["$1"]}
Просто другая идея добавить к уже широкому набору опций из превосходного ответа Serg.
Вы смогли использовать alias
для этого - возможно с некоторыми небольшими изменениями в том, как Вы в настоящее время делаете вещи.
alias
просто слово, которое Вы принимаете решение отобразить на большую строку, которую развернет оболочка каждый раз, когда она встречается с ним. Возможно, обычно замеченный вариант использования состоит в том, чтобы применить 'значения по умолчанию' к существующей команде, как это:
alias ls='ls -a --color=auto'
Однако нет никакого требования что Ваш alias
должен быть назван в честь существующей команды - или еще короче, чем ее шаблон назначения - таким образом, Вы могли, например. alias tgzcreator='tar -czvf'
alias
es совместно используют время жизни с оболочкой, в которой они определяются. 'Персистентный' alias
es для Вас может быть настроен в ~/.bash_aliases
, который должен быть получен автоматически большей частью правильно написанного значения по умолчанию .bashrc
сценарии и тому подобный.
Примечание несколько подсказок:
alias
вмешается в Ваш код, можно снабдить префиксом его обратную косую черту для обеспечения alias
луг пропускается. например, Я обычно alias
cp
кому: cp -i
чтобы не случайно перезаписывать вещи, но в некоторых сценариях, я ясно хочу перезаписать вещи. (Я не собираюсь использовать некоторое ужасное обходное решение как установка известной ООНalias
пользователь редактора!) Так, в том сценарии, я буду использовать \cp src dst
alias
es не может быть получен по умолчанию в рамках сценариев оболочки, которые запускают их собственную неинтерактивную копию оболочки. Можно удостовериться, что они расширены путем установки опции expand_aliases
в Вашем сценарии. Я получил это от: https://stackoverflow.com/questions/2197461/how-to-set-an-alias-inside-a-bash-shell-script-so-that-is-it-visible-from-the-ouТак, базируясь от ограниченного контекста, доступного в Вашем сообщении, Вы могли бы хотеть сделать что-то отчасти как это:
shopt -s expand_aliases
alias get_etc_dir='find /etc -type d'
alias get_etc_fil='find /etc -type f'
Для Вас это не может работать без тонкой настройки, например, изменения Вашего параметризованного типа inode в суффикс на псевдоним. Это - просто другая опция для того, как пользователи могут сократить биты кода в целом. Так или иначе я попытался объяснить всесторонне на основе того, что я знаю, и я надеюсь, что это полезно где-нибудь.
(Кроме того, я предложил бы переместить это в Unix/Linux SE, предположив, что это - идеал для вещей, которые не являются определенными для Ubuntu?)