Как я могу сгенерировать случайную строку ответа вроде "да, нет, а может быть и нет?

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

Переменные среды — это свойство, которым обладают ВСЕ процессы, независимо от того, используют они их внутри или нет. Даже sleep 10 во время работы имеет переменные окружения. Точно так же, как у всех процессов есть PID (идентификатор процесса), текущий рабочий каталог (cwd), PPID (родительский PID), список аргументов (даже если он пустой) и так далее. Точно так же все процессы имеют так называемую «среду», которая наследуется от родительского процесса при его разветвлении.

С точки зрения автора утилиты (того, кто пишет код на C), процессы могут устанавливать, сбрасывать или изменять переменные среды. Однако, с точки зрения автора сценария, большинство инструментов не предлагают такую ​​возможность своим пользователям. Вместо этого вы используете свою оболочку для изменения среды процесса, которая затем наследуется при выполнении вызванной вами команды (внешнего двоичного файла). (Среда вашей оболочки может быть изменена, и модификация унаследована, или вы можете указать своей оболочке сделать модификацию после разветвления, но до выполнения вызванной вами команды. В любом случае среда наследуется. Мы рассмотрим оба варианта. подходов.)

Переменные оболочки — это другое дело. Хотя внутри оболочки они ведут себя одинаково, разница в том, что простые "переменные оболочки" не изменяют и не влияют на поведение команд, которые вы вызываете из вашей оболочки. В надлежащей терминологии это различие на самом деле было бы сформулировано немного по-другому; экспортированные переменные оболочки станут частью среды инструментов, которые вы вызываете, тогда как переменные оболочки, которые не экспортируются, не будут. Тем не менее, я считаю более полезным для связи ссылаться на переменные оболочки, которые не экспортируются, как на «переменные оболочки», и переменные оболочки, которые экспортируются как «переменные среды», потому что они являются средой. переменные с точки зрения процессов, разветвленных из оболочки.


Много текста.Давайте рассмотрим несколько примеров и опишем, что происходит:

$ somevar=myfile
$ ls -l "$somevar"
-rw-r--r--  1 Myname  staff  0 May 29 19:12 myfile
$ 

В этом примере somevar — это просто переменная оболочки, в ней нет ничего особенного. Оболочка расширение параметров (см. LESS='+/Расширение параметров' man bash) происходит до исполняемого файла ls фактически загружается (" exec"ed), а команда ls (процесс) никогда даже не видит строку "знак доллара somevar". Он видит только строку "m-y-f-i-l-e", интерпретирует ее как путь к файлу в текущем рабочем каталоге, получает и печатает информацию о нем.

Если мы запустим export somevar перед командой ls, то тот факт, что somevar=myfile появится в окружении файла процесс ls, но это ни на что не повлияет, потому что команда ls ничего не сделает с этой переменной. Чтобы увидеть эффект переменной среды, мы должны выбрать переменную среды, которую вызываемый нами процесс действительно будет проверять и что-то делать с ней.


bc: Базовый калькулятор

Возможно, есть лучший пример, но этот не слишком сложный, который придумал я. Во-первых, вы должны знать, что bc — это базовый калькулятор, который обрабатывает и вычисляет математические выражения. (После обработки содержимого любых входных файлов он обрабатывает свой стандартный ввод. Я не буду использовать его стандартный ввод для своих примеров, я просто нажму Ctrl-D, что не будет отображаться в текстовых фрагментах ниже.Также я использую -q для подавления вводного сообщения при каждом вызове.)

Переменная окружения, которую я проиллюстрирую, описана в man bc:

   BC_ENV_ARGS
      This is another mechanism to get arguments to bc.  The format is
      the  same  as  the  command line arguments.  These arguments are
      processed first, so any files listed in  the  environment  argu-
      ments  are  processed  before  any  command line argument files.
      This allows the user to set up "standard" options and  files  to
      be  processed at every invocation of bc.  The files in the envi-
      ronment variables would typically contain  function  definitions
      for functions the user wants defined every time bc is run.

Вот:

$ cat file1
5*5
$ bc -q file1
25
$ cat file2
6*7
8+9+10
$ bc -q file2
42
27
$ bc -q file1 file2
25
42
27
$

Это просто для того, чтобы показать, как работает bc.В каждом из этих случаев мне приходилось нажимать Ctrl-D, чтобы сигнализировать «конец ввода» для bc.

Теперь давайте передадим переменную среды непосредственно в bc:

$ BC_ENV_ARGS=file1 bc -q file2
25
42
27
$ echo "$BC_ENV_ARGS"

$ bc -q file2
42
27
$

Обратите внимание, что то, что мы помещаем в эту переменную, не видно позже из echo. Поместив присваивание как часть той же команды (тоже без точки с запятой), мы поместили это присваивание переменной как часть окружения bc — оно оставило саму оболочку, которую мы работают без изменений.

Теперь установим BC_ENV_ARGS в качестве переменной оболочки:

$ BC_ENV_ARGS=file1
$ echo "$BC_ENV_ARGS"
file1
$ bc -q file2
42
27
$

Здесь видно, что наша команда echo может видеть содержимое, но не часть окружения bc, поэтому bc ничего особенного с ним сделать не может.

Конечно, если мы поместим саму переменную в список аргументов bc, мы увидим кое-что:

$ bc -q "$BC_ENV_ARGS"
25
$ 

Но здесь это оболочка, расширяющая переменную, а затем file1 — это то, что на самом деле появляется в bc в списке аргументов . Таким образом, он по-прежнему используется как переменная оболочки, а не как переменная среды.

Теперь давайте «экспортируем» эту переменную, чтобы она была и переменной оболочки, и переменной окружения:

$ export BC_ENV_ARGS
$ echo "$BC_ENV_ARGS"
file1
$ bc -q file2
25
42
27
$

Здесь вы можете видеть, что файл1 обрабатывается раньше файл2, хотя здесь не упоминается в командной строке.Это часть среды оболочки и становится частью среды bc при запуске этого процесса, поэтому значение этой переменной среды наследуется и влияет на то, как bc ] действует.

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

$ BC_ENV_ARGS= bc -q file2
42
27
$ echo "$BC_ENV_ARGS"
file1
$ bc -q file2
25 
42
27
$ 

Но, как вы видите, переменная остается установленной и экспортируется в нашу оболочку, видимая как самой оболочке, так и любые более поздние команды bc, которые не переопределяют значение. Он останется таким, если мы не «отменим экспорт» или «отключим» его. Я сделаю последнее:

$ unset BC_ENV_ARGS
$ echo "$BC_ENV_ARGS"

$ bc -q file2
42
27
$ 

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

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

# fruit is not set
echo "$fruit"
sh -c 'echo "$fruit"'
# fruit is set as a shell variable in the current shell only
fruit=apple
echo "$fruit"
sh -c 'echo "$fruit"'
sh -c "echo $fruit" ### NOT advised for use in scripts, for illustration only
# fruit is exported, so it's accessible in current AND new processes
export fruit
echo "$fruit"
sh -c 'echo "$fruit"'
echo '$fruit' ### I threw this in to make sure you're not confused on quoting
# fruit is unset again
unset fruit
echo "$fruit"
sh -c 'echo "$fruit"'
# setting fruit directly in environment of single command but NOT in current shell
fruit=apple sh -c 'echo "$fruit"'
echo "$fruit"
fruit=apple echo "$fruit"
# showing current shell is unaffected by directly setting env of single command
fruit=cherry
echo "$fruit"
fruit=apricot sh -c 'echo "$fruit"'
echo "$fruit"
sh -c 'echo "$fruit"'

И последнее для дополнительной хитрости: можете ли вы предсказать вывод следующих команд, выполняемых последовательно? :)

fruit=banana
fruit=orange sh -c 'fruit=lemon echo "$fruit"; echo "$fruit"; export fruit=peach'
echo "$fruit"

Пожалуйста, укажите в комментариях любые желаемые разъяснения; Я уверен, что это могло бы использовать несколько. Но, надеюсь, это должно быть полезно даже в том виде, в котором оно есть.

0
29.03.2019, 18:12
1 ответ
#!/bin/bash

array=( yes no maybe )
read -p 'do you hate me ? [press a key] >>> '
echo ${arr[RANDOM % ${#array[@]}]}
4
28.01.2020, 02:18

Теги

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