Параметры скрипта в Bash

104

Я пытаюсь создать сценарий оболочки, который следует использовать следующим образом:

ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

Затем сценарий ocr преобразует файл изображения в текстовый файл. Вот что я до сих пор придумал:

#!/bin/bash
export HOME=/home/kristoffer
/usr/local/bin/abbyyocr9 -rl Swedish -if ???fromvalue??? -of ???tovalue??? 2>&1

Но я не знаю , как получить -fromи -toзначение. Есть идеи, как это сделать?

Кристоффер
источник
6
прочтите tldp.org/LDP/Bash-Beginners-Guide/html/…
Mehul Rathod 01

Ответы:

125

Аргументы , которые вы предоставляете в bashscript появятся в переменных $1и $2и $3где число относится к аргументу. $0это сама команда.

Аргументы разделяются пробелами, поэтому, если вы укажете -fromи -toв команде, они тоже окажутся в этих переменных, поэтому для этого:

./ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

Ты получишь:

$0    # ocrscript.sh
$1    # -from
$2    # /home/kristoffer/test.png
$3    # -to
$4    # /home/kristoffer/test.txt

Было бы проще опустить -fromи -to, например:

ocrscript.sh /home/kristoffer/test.png /home/kristoffer/test.txt

Тогда у вас будет:

$1    # /home/kristoffer/test.png
$2    # /home/kristoffer/test.txt

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

Тогда вы сможете:

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

Двойные кавычки вокруг $1и $2не всегда необходимы, но рекомендуется, потому что некоторые строки не будут работать, если вы не поместите их между двойными кавычками.

гитаарик
источник
69

Если вы не совсем привязаны к использованию «from» и «to» в качестве имен опций, довольно легко реализовать это с помощью getopts :

while getopts f:t: opts; do
   case ${opts} in
      f) FROM_VAL=${OPTARG} ;;
      t) TO_VAL=${OPTARG} ;;
   esac
done

getopts это программа, которая обрабатывает аргументы командной строки и анализирует их за вас.

f:t:указывает, что вы ожидаете 2 параметра, которые содержат значения (обозначенные двоеточием). Что-то вроде f:t:vговорит, что -vэто будет интерпретироваться только как флаг.

optsгде хранится текущий параметр. В caseзаявлении вы будете это обрабатывать.

${OPTARG}содержит значение, следующее за параметром. ${FROM_VAL}например, получит значение, /home/kristoffer/test.pngесли вы запустили свой скрипт, например:

ocrscript.sh -f /home/kristoffer/test.png -t /home/kristoffer/test.txt

Как предлагают другие, если вы впервые пишете сценарии bash, вам действительно стоит прочитать некоторые основы. Это было просто краткое руководство о том, как это getoptsработает.

Мэнни Д.
источник
1
Кажется, это удобочитаемое решение. Как бы вы тогда указали два флага?
Zelphir Kaltstahl
@Zelphir, вы можете указать два или более флага, просто опуская ":" после флага. Например f:t:vsбудет-f some_f -t some_t -v -s
h_s
35

Используйте переменные "$1", "$2", "$3"и так далее аргументы доступа. Для доступа ко всем из них вы можете использовать "$@"или для получения количества аргументов $#(может быть полезно проверить слишком мало или слишком много аргументов).

StianE
источник
24

Мне нужно было убедиться, что мои скрипты полностью переносимы между различными машинами, оболочками и даже версиями cygwin. Кроме того, мои коллеги, для которых мне пришлось писать сценарии, были программистами, поэтому в итоге я использовал это:

for ((i=1;i<=$#;i++)); 
do

    if [ ${!i} = "-s" ] 
    then ((i++)) 
        var1=${!i};

    elif [ ${!i} = "-log" ];
    then ((i++)) 
        logFile=${!i};  

    elif [ ${!i} = "-x" ];
    then ((i++)) 
        var2=${!i};    

    elif [ ${!i} = "-p" ]; 
    then ((i++)) 
        var3=${!i};

    elif [ ${!i} = "-b" ];
    then ((i++)) 
        var4=${!i};

    elif [ ${!i} = "-l" ];
    then ((i++)) 
        var5=${!i}; 

    elif [ ${!i} = "-a" ];
    then ((i++)) 
        var6=${!i};
    fi

done;

Обоснование: я также включил launcher.shсценарий, так как вся операция состояла из нескольких шагов, которые были квазинезависимыми друг от друга (я говорю «квази», потому что, хотя каждый сценарий мог запускаться отдельно, они обычно выполнялись вместе. ), и через два дня я узнал, что примерно половина моих коллег, программистов и все такое, были слишком хороши, чтобы использовать файл пусковой установки, следить за «использованием» или читать СПРАВКУ, которая отображалась каждый раз, когда они что-то делали. неправильно, и они все испортили, запускали сценарии с аргументами в неправильном порядке и жаловались, что сценарии не работают должным образом. Поскольку я холерик, я решил переделать все свои скрипты, чтобы убедиться, что они защищены от коллег. Приведенный выше сегмент кода был первым.

user1628658
источник
2
Мне это нравится. Я добавляю раздел в конце `else echo" Недопустимый аргумент: $ {! I} "((i ++))
fi`
6

В bash $1это первый аргумент, переданный скрипту, $2второй и т. Д.

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

Итак, вы можете использовать:

./your_script.sh some_source_file.png destination_file.txt

Пояснение к двойным кавычкам;

рассмотрим три сценария:

# foo.sh
bash bar.sh $1

# cat foo2.sh
bash bar.sh "$1"

# bar.sh
echo "1-$1" "2-$2"

Теперь вызовите:

$ bash foo.sh "a b"
1-a 2-b

$ bash foo2.sh "a b"
1-a b 2-

Когда вы вызываете, foo.sh "a b"он вызывает bar.sh a b(два аргумента), а вместе с foo2.sh "a b"ним вызывает bar.sh "a b"(1 аргумент). Всегда помните, как параметры передаются и раскрываются в bash, это избавит вас от много головной боли.

Якуб М.
источник