Как определить использование подстановочного знака (звездочка *) в качестве параметра для сценария оболочки? - PullRequest
3 голосов
/ 13 сентября 2010

Как в моем скрипте отличить использование подстановочного знака звездочки вместо строго типизированных параметров?

Это

# myscript *

от этого

# myscript p1 p2 p3 ... (where parameters are unknown number)

Ответы [ 6 ]

7 голосов
/ 04 мая 2011

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

Решение Тома отлично, если вы хотите обнаружить, но я бы предпочел предотвратить. Другими словами, если бы у меня был скрипт под названием findin, который выглядел бы как

#!/bin/bash
echo "[${1}]"

и запустил его, используя:

$ findin *

Я ожидаю, что результат будет просто

[*]

Чтобы сделать это, вы можете просто найти псевдоним

alias findin='set -f; /path/to/findin'

Но тогда у вас будет установлен параметр оболочки до конца сеанса. Это, вероятно, сломает многие программы, которые этого не ожидают (например, ls -lh * .py). Вы можете проверить это, набрав

echo $-

в консоли. Если вы видите f, эта опция установлена.

Вы можете вручную удалить эту опцию, набрав

set +f

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

Поскольку сценарии оболочки порождают подоболочки, и вы не можете очистить флаг из сценария (set + f), я пришел к следующему решению:

g(){ /usr/local/bin/findin "$@"; set +f; }
alias findin='set -f; g'

Примечание: «g» может быть не лучшим названием для функции, поэтому рекомендуется изменить его.

Наконец, вы можете обобщить это, выполнив что-то вроде:

reset_expansion(){ CMD="$1"; shift; $CMD "$@"; set +f; }
alias findin='set -f; reset_expansion /usr/local/bin/findin'

Таким образом, для другого сценария, в котором вы хотите отключить расширение, потребуется только дополнительный псевдоним, например,

alias newscript='set -f; reset_expansion /usr/local/bin/newscript'

, а не дополнительная функция оболочки.

Для более длинного, чем необходимо, написания, см. мой пост здесь .


7 голосов
/ 13 сентября 2010

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

Это означает, что вашему сценарию потребуется помощь от чего-либоеще что не является сценарием.В частности, то, что запускается перед обработкой из командной строки.Это что-то псевдоним.Это ваш псевдоним

alias myscript='set -f; globstopper /usr/bin/myscript'

Для этого создается псевдоним под названием «myscript», поэтому, когда кто-то вводит «myscript», он запускается.Псевдоним делает две вещи: во-первых, он отключает расширение по шаблону с помощью set -f, затем он запускает функцию с именем globstopper, передавая путь к вашему сценарию и остальные аргументы командной строки.

Так что же такое функция globstopper?Это:

globstopper() {
  if [[ "$2" == "*" ]]
    then echo "You cannot use a wildcard"
    return
  fi
  set +f
  "$@";
}

Эта функция делает три вещи.Во-первых, он проверяет, является ли аргумент сценария подстановочным знаком (caveat: он проверяет только первый аргумент и только проверяет, является ли он простой звездой; расширение его для охвата большего числа случаев оставлено в качестве упражнения длячитатель).Во-вторых, он снова включает расширение по шаблону.Наконец, он запускает оригинальную команду.

Чтобы это работало, вам нужно иметь возможность настроить псевдоним и функцию оболочки в пользовательской оболочке и требовать от пользователей использовать псевдоним, а нескрипт.Но если вы можете сделать это, это должно сработать.

Я должен добавить, что я в значительной степени опираюсь на эссе великолепного Саймона Тэтхэма " Магические псевдонимы: лазейка в раковине Борна "Вот.

3 голосов
/ 13 сентября 2010

Вы не можете.

Это одна из сильных сторон (или, в некоторых глазах, слабых сторон) Unix.

См. Раздел (ы) в «Справочник UNIX-HATERS» .

1 голос
/ 25 января 2013

Добавление

Я нашел этот пост, когда искал обходной путь для моего калькулятора командной строки:

alias c='set -f; call_clc'

where "call_clc" is the function: "function call_clc { clc "$*"; set +f; }"

and "clc" is the script
#!/bin/bash
echo "$*" | sed -e 's/ //g' >&1 | tee /dev/tty | bc

Мне нужны 'set -f' и 'set +f', чтобы такие входы, как 'c 4 * 3', работали, поэтому звездочка с пробелами до и после, для того, чтобы предотвратить слипание удара.

Обновление: предыдущий вариант alias c='set -f; clc "$*"; set+f;' не работал потому что по какой-то причине правильный результат был получен после вызова команды "c 4 * 4 'дважды. У кого-нибудь есть идея, почему это так?

1 голос
/ 13 сентября 2010
$arg_num == ***; // detects *(literally anything since it's a global wildcard)
$arg_num == *_*; // detects _

вот пример того, как он работает с _

for i in $*
  do
    if [[ "$i" == *_* ]]; 
      then echo $i; 
    fi
  done

выводом . / Bash test * test2 _

_

выводом. / Bash test * test2 с ********* вместо ****

test
bash
pass.rtf
test2
_

ПРИМЕЧАНИЕ: * является настолько глобальнымв bash он распечатал файлы, соответствующие этому описанию, или, в моем случае, файлы на моем «не очень-то» рабочем столе.Хотел бы я дать вам лучший ответ, но лучший выбор - использовать что-то другое, чем * или другой язык сценариев.

0 голосов
/ 13 сентября 2010

Если это то, что вы чувствуете, что должны сделать, возможно:

# if the number of parms is not the same as the number of files in cwd
# then user did not use *
dir_contents=(*)
if [[ "${#@}" -ne "${#dir_contents[@]}" ]]; then 
    used_star=false
else
    # if one of the params is not a file in cwd
    # then user did not use *
    used_star=true
    for f; do [[ ! -a "$f" ]] && { used_star=false; break; }; done
fi
unset dir_contents

$used_star && echo "used star" || echo "did not use star"

Педантически это будет отображать "использованную звезду", если пользователь фактически использовал звездочку или если пользователь вручную вводил содержимое каталога в любом порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...