Как условно передать аргумент из сценария оболочки POSIX?

Будьте осторожны, cat не является идеальным инструментом для отображения данных, которые могут быть двоичными.

Простым инструментом для Unix является od(восьмеричный дамп ).

Пример od -c -tx1

root@server:~# od -c -tx1 /etc/passwd | head
0000000   r   o   o   t   :   x   :   0   :   0   :   r   o   o   t   :
         72  6f  6f  74  3a  78  3a  30  3a  30  3a  72  6f  6f  74  3a
0000020   /   r   o   o   t   :   /   b   i   n   /   b   a   s   h  \n
         2f  72  6f  6f  74  3a  2f  62  69  6e  2f  62  61  73  68  0a
0000040   d   a   e   m   o   n   :   x   :   1   :   1   :   d   a   e
         64  61  65  6d  6f  6e  3a  78  3a  31  3a  31  3a  64  61  65
0000060   m   o   n   :   /   u   s   r   /   s   b   i   n   :   /   u
         6d  6f  6e  3a  2f  75  73  72  2f  73  62  69  6e  3a  2f  75
0000100   s   r   /   s   b   i   n   /   n   o   l   o   g   i   n  \n
         73  72  2f  73  62  69  6e  2f  6e  6f  6c  6f  67  69  6e  0a

так что вы можете видеть, что возврат каретки \n

16
19.01.2020, 19:25
5 ответов

Изменение исходного сценария:

#!/bin/sh
echo "Noise $1"
echo "Enhancement $2"
for snr in 0 5 10 15 20 25
do
  python evaluate.py --noise "$1" --snr "$snr" --iterations 1250 ${2:+--enhancement "$2"}
done

Расширение стандартного параметра${var:+word}будет расширено до word, если переменная varустановлена ​​и не пуста. В приведенном выше коде мы используем его для добавления --enhancement "$2"к команде, если $2доступно и не пусто.

Я также позволил себе предположить, что то, что вы передаете --snrв качестве аргумента option -, должно быть значением переменной цикла.


Мой личный подход к коду (в основном просто использует printf, а не echo, избегая длинных строк и придавая коду немного больше воздуха):

#!/bin/sh

printf 'Noise %s\n' "$1"
printf 'Enhancement %s\n' "$2"

for snr in 0 5 10 15 20 25; do
    python evaluate.py \
        --noise "$1" \
        --snr "$snr" \
        --iterations 1250 \
        ${2:+--enhancement "$2"}
done

Как указывает mosvy в комментариях ниже. :Если ваш /bin/shявляется оболочкой dashили какой-либо другой оболочкой, которая неправильно сбрасывает IFSпри запуске нового сеанса оболочки (, это требуется POSIX ), и если вы по той или иной причине экспортировали IFSи присвоили ему значение по умолчанию, отличное от -, то вы можете использовать unset IFSв начале приведенного выше сценария.

Делайте это всякий раз, когда вы исправите все другие проблемы, которые, несомненно, возникли при экспорте IFS(не экспортироватьIFS).

32
27.01.2020, 19:48

В минимальной оболочке POSIX, которая не поддерживает массивы, вы можете просто манипулировать списком позиционных аргументов с помощью команды set. Непосредственно перед циклом forвы можете сделать

if [ -z "$2" ]; then
    set -- --noise "$1" --snr 25 --iterations 1250
else
    set -- --noise "$1" --snr 25 --iterations 1250 --enhancement "$2"
fi

и теперь запустите цикл for как

for snr in 0 5 10 15 20 25; do
    python evaluate.py "$@"
done

Если ваша оболочка поддерживает повторную оболочку массива bash, zshили другую, вы можете просто использовать массив

argv=(--noise "$1" --snr 25 --iterations 1250)

if [ ! -z "$2" ]; then
    argv+=( --enhancement "$2" )
fi

и теперь вызовите скрипт как

python evaluate.py "${argv[@]}"

Как указано в комментариях, вы не используете фактическое значение значения snrиз цикла for. Используйте значение как $snr, где это применимо в аргументах скрипта, и в этом случае вам может понадобиться переместить логику построения списка аргументов внутрь цикла.

13
27.01.2020, 19:48

Создание аргумента в переменной на основе ввода:

#!/bin/sh
echo "Noise $1"
echo "Enhancement $2"

if [ $# -eq 1 ]
then
   enhance=""
else
   enhance="--enhancement $2"
fi

for snr in 0 5 10 15 20 25
do
  python evaluate.py --noise $1 --snr "$snr" --iterations 1250 $enhance
done

(Также включает исправление переменной цикла в теле цикла)

2
27.01.2020, 19:48

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

  python evaluate.py --noise $1 --snr 25 --iterations 1250 $(test -n "$2" && echo --enhancement "$2")
2
27.01.2020, 19:48

Единственный способ сделать так, чтобы раскрытие переменной исчезло, — это раскрыть раскрытие до пустого значения, когда это раскрытие не заключено в кавычки.

$ unset a; b=''; c=set
$ printf '<%s> ' unquoted $a $b quoted "$a" "$b" val $c "$c"; echo
<unquoted> <quoted> <> <> <val> <s> <t> <set>

Как неустановленные, так и пустые значения переменных(aиb)исчезают (в качестве аргументов ), если они не заключены в кавычки. Оба сохраняются при цитировании.

Кроме того, даже пробелы (или любой символ )исчезнут, если они включены в IFS.

$ IFS=' '
$ unset a; b=' '; c='  set  '
$ printf '<%s> ' unquoted $a $b quoted "$a" "$b" val $c "$c"; echo
<unquoted> <quoted> <> < > <val> <set> <  set  >

Фактически, IFS, содержащая символы в значении для расширения (без кавычек ), будет разделять аргументы.

$ IFS='e '
$ $ printf '<%s> ' unquoted $a $b quoted "$a" "$b" val $c "$c"; echo
<unquoted> <quoted> <> < > <val> <s> <t> <  set  >

Обратите внимание на два аргумента <s>и <t>, возникшие в результате раскрытия значения set, когда IFS содержало e.

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

${var:+"$var"}

Описание:

${             # starts an un-quoted variable expansion
  var          # name of variable to expand
     :         # also replace if var is null
      +        # use what follows if is not unset (nor null)
       "$var"  # a quoted variable expansion.
             } # end of expansion.

# In short: expand "$var" if it has a value, $var otherwise.

Затем мы можем использовать значение $1, чтобы либо убрать его, либо расширить

echo ${1:+"--noise"} ${1:+"$1"}

В приведенной выше строке будет либо напечатано два отдельных аргумента (, не затронутых IFS ), если $1имеет некоторое (ненулевое )значение, либо ничего, если $1пустой или не установлен.

Скрипт станет:

#!/bin/sh
echo "Noise $1"
echo "Enhancement $2"

for    snr in 0 5 10 15 20 25
do     python evaluate.py \
         ${1:+"--noise"} ${1:+"$1"} \
         --snr "$snr" \
         --iterations 1250 \
         ${2:+"--enhancement"} ${2:+"$2"}
done

На это решение не влияет значение IFS

0
27.01.2020, 19:48

Теги

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