Отключить буферизацию файловых дескрипторов в bash

В bash массивы могут быть либо индексированными либо ассоциативными . Индексированные массивы имеют числовой индекс и (по умолчанию )перебираются в соответствии с числовым порядком их индексов.

Ассоциативный массив (, также известный как hashилиhashed array)в bash, может использовать любую строку в качестве индекса (, также известного как key)-, эта строка может быть числовой (или казаться числовой, в скрипте bash )мало различий, или это может быть любая другая допустимая строка.

Ассоциативные массивы в bash, как и во многих языках, неупорядочены. Если вы просто перебираете массив (, например. без сортировки ключей )вы получите элементы массива в полуслучайном -порядке.

Массивы в bash по умолчанию являются индексированными массивами. Вы можете явно объявить индексированный массив сdeclare -a(строчными буквами a. Независимо от того, будет ли declared индексироваться или создан как индексированный массив по умолчанию, если вы попытаетесь установить элемент массива с числовым индексом, отличным от -, индекс всегда будет оцениваться как 0, переопределять или создавать значение (если есть )нулевого элемента массива.

напр.

$ declare -a foo
$ foo[0]=5
$ foo[1]=2
$ declare -p foo
declare -a foo=([0]="5" [1]="2")

Ладно, этого и следовало ожидать. А теперь попробуйте установитьfoo[bar]:

$ foo[bar]=99
$ declare -p foo
declare -a foo=([0]="99" [1]="2")

Точно так же вы можете объявить массив ассоциативным с помощьюdeclare -A(обратите внимание на заглавнуюA). Это заставит массив быть ассоциативным, даже если ВСЕ индексы являются числовыми.

$ unset foo
$ declare -A foo
$ foo[0]=5
$ foo[1]=2
$ foo[bar]=99
$ declare -p foo
declare -A foo=([bar]="99" [0]="5" [1]="2" )

Итак, ответ на ваш вопрос заключается в том, что в примере _1 вы объявили cityассоциативным массивом . В примере _2 вы этого не сделали, поэтому по умолчанию это массив с индексом .

0
27.10.2019, 23:36
1 ответ
#### This always works OK, but can't use it in my scenario
foo "1" > >(log) > test_out.txt
foo "2" > >(log) >> test_out.txt

Подстановки процессов здесь кажутся излишними, поскольку следующие перенаправления переопределяют перенаправление stdout прямо в файл. То есть первый должен быть эквивалентен foo "1" > test_out.txt.

#### This is similar to what I need to do and always fails
exec >test_out.txt
foo "1" > >(log)
foo "2" > >(log)

Здесь, я думаю, проблема в том, что подстановка процесса выполняется асинхронно, и поскольку цикл while read; do echoмедленный, первый logвсе еще работает и читает из буферов канала, когда запускается второй. Это похоже на выполнение чего-то вроде echo foo > >(cat; sleep 1; echo hi)в командной строке, hiпоявляется сразу после отображения следующего приглашения. Кроме того, waitздесь тоже не помогает.

Но я не совсем понимаю, зачем вообще нужны две копии log? Один бы не сделал:

exec >test_out.txt
exec 9> >(log)
foo "1" >&9
foo "2" >&9

(В моей системе использование catвместо while read; do echoтакже, по крайней мере, скрывает проблему, так как catнамного быстрее и читает большими блоками. Но это не значит, что это полностью исправит это, и вы, вероятно, захотите сделать что-то другое, а не просто идентичную копию в log.)

I should add that I know about external tools which can disable buffering for a command

Если вы имеете в виду такие вещи, как stdbuf -o0, это помогает только с буферизацией внутри процесса (в библиотеке C ), что, я думаю, здесь не играет роли. Оболочка echoдолжна фактически записать данные в ОС перед возвратом.

0
28.01.2020, 03:10

Теги

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