То, как я могу минимизировать код, должно было выполнить эту пользовательскую функцию?

Я хотел бы сократить один из своих сценариев, и я получил 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

4
задан 12 November 2015 в 02:47

5 ответов

Существует несколько возможных способов упростить код. Ниже решения, заказанные объемом кода:

  1. printf и замена параметра (никакая проверка ошибок)
  2. xargs и замена параметра (никакая проверка ошибок)
  3. find и параметр substition только (никакая проверка ошибок)
  4. провалитесь выбирающая структура (Решает проблему проверки ошибок),
  5. Протестируйте логику, xargs, и замену параметра
  6. Функция Bash
  7. Массив, для цикла, тест и &&

  1. 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, которого функциональное решение избегает - функциональная и выбирающая структура является всеми собственными инструментами удара.

  2. 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, потому что мы берем первый символ любой строки …, Другими словами, нет никакой проверки ошибок.

  3. find с расширением параметра

    Используя расширение параметра еще больше, мы можем сделать это:

     find /etc -type ${1:0:1}
    

    В основном, острота с find команда и подстрока $1 переменная. Кроме того, никакая проверка ошибок.

  4. Провалитесь выбирающая структура

    Большой проблемой с последними тремя методами является проверка ошибок. Они хороши, когда Вы доверяете пользователю, чтобы не быть макетом или просто написанием кода для себя. Теперь, в 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.
  1. Функциональное решение

    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
    
  2. Массив, для цикла, тест и &&

    Основная идея здесь - соответствует входу пользователя против списка и, если подобрано делает что-то. Мы создаем массив объектов, чтобы проверить на, иметь условие испытания (квадратные скобки по тому, как псевдоним к 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  
    
7
ответ дан 23 November 2019 в 11:36

Поместите его в функцию:

MyFind () {
  COMMAND="find /etc -type "
  case $1:
   "directory") $COMMAND d
   ;;
  esac
}

Теперь Вы можете всегда использовать его в качестве MyFind $TYPE

<час>

Относительно Вашего 1-го комментария

, Вы можете также поместить только заявление случая в функцию

FType () {
  case $1 in
    "directory") echo d;;
    "file") echo f;;
  esac
}

COMMAND="find /etc -type "
$COMMAND $(FType $TYPE) 
4
ответ дан 23 November 2019 в 11:36
[[ "$1" == "directory" ]] && find /etc -type d
2
ответ дан 23 November 2019 в 11:36

Другой подход:

declare -A foo    # associative array

foo["directory"]="d"
foo["file"]="f"
foo["link"]="l"

find /etc -type ${foo["$1"]}
2
ответ дан 23 November 2019 в 11:36

Просто другая идея добавить к уже широкому набору опций из превосходного ответа Serg.

Вы смогли использовать alias для этого - возможно с некоторыми небольшими изменениями в том, как Вы в настоящее время делаете вещи.

alias просто слово, которое Вы принимаете решение отобразить на большую строку, которую развернет оболочка каждый раз, когда она встречается с ним. Возможно, обычно замеченный вариант использования состоит в том, чтобы применить 'значения по умолчанию' к существующей команде, как это:

alias ls='ls -a --color=auto'

Однако нет никакого требования что Ваш alias должен быть назван в честь существующей команды - или еще короче, чем ее шаблон назначения - таким образом, Вы могли, например. alias tgzcreator='tar -czvf'

aliases совместно используют время жизни с оболочкой, в которой они определяются. 'Персистентный' aliases для Вас может быть настроен в ~/.bash_aliases, который должен быть получен автоматически большей частью правильно написанного значения по умолчанию .bashrc сценарии и тому подобный.

Примечание несколько подсказок:

  • Вместо того, чтобы вызывать беспокойство в конкретном сценарии ли ранее определенный alias вмешается в Ваш код, можно снабдить префиксом его обратную косую черту для обеспечения aliasлуг пропускается. например, Я обычно alias cp кому: cp -i чтобы не случайно перезаписывать вещи, но в некоторых сценариях, я ясно хочу перезаписать вещи. (Я не собираюсь использовать некоторое ужасное обходное решение как установка известной ООНaliasпользователь редактора!) Так, в том сценарии, я буду использовать \cp src dst
  • aliases не может быть получен по умолчанию в рамках сценариев оболочки, которые запускают их собственную неинтерактивную копию оболочки. Можно удостовериться, что они расширены путем установки опции 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?)

1
ответ дан 23 November 2019 в 11:36

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

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