Какова именно длина массива в bash и как различать «*» и «@»?

Давным-давно был оконный менеджер под названием twm - на самом деле, он все еще существует и отлично работает. Вместо того, чтобы сворачивать окно до панели внизу экрана (или подобного), как в MS Windows, Mac OS X и многих современных оконных менеджерах, он сжал их до помеченных значков («iconfify»).

В статье Wikipedia twm есть несколько красивых картинок, например:

Screenshot from TWM

Заголовок окна - это то, что отображается в строке заголовка (например, «Калькулятор» или «xterm»). Имя значка - это то, что идет под значком при значении («xclock»). Современные оконные менеджеры, вероятно, все игнорируют имя значка, потому что они не используют пользовательский интерфейс значка.

Полное описание обоих можно найти в ICCCM .

0
13.03.2018, 18:03
2 ответа

Вы пропустили случай, когда он показывает, что *расширяет массив до одной строки, а @расширяет до отдельных строк в кавычках:

printf 'string "%s"\n' "${cape[*]}"

, который генерирует

string "Ping Pong King Kong King Fisher Club Blurb"

и

printf 'string "%s"\n' "${cape[@]}"

, который генерирует

string "Ping Pong"
string "King Kong"
string "King Fisher Club"
string "Blurb"

Помните, что echoпросто объединяет свои аргументы и печатает их, в то время как printfзаполняет свою строку формата аргументами и повторяет тот же формат, если предоставлено больше аргументов.

Кроме того,

for s in "${cape[*]}"; do
    echo "$s"
done

генерирует одну строку вывода (он повторяет только одну строку ), а

for s in "${cape[@]}"; do
    echo "$s"
done

генерирует по одному элементу массива.


Вы всегда должны использовать двойные кавычки вокруг расширений ${array[*]}и ${array[@]}, если вы по какой-то причине не хотите явно вызывать разбиение слов и подстановку имен файлов.И вы используете *или @в зависимости от того, нужны ли вам элементы массива все вместе как одна строка или по отдельности.

По моему опыту, очень редко используется [*].


При получении длины массива не имеет значения, какой из *или @вы используете. Но если вы не используете ни то, ни другое, вы получите длину в символах первого элемента массива.

5
28.01.2020, 02:18

Основываясь на различных кавычках, которые вы использовали в назначениях переменных, я полагаю, что вы неверно истолковали фразу «если слово в двойных -кавычках или нет» означает «если элемент массива (s )заключены в двойные -кавычки», в то время как в руководстве подразумевается «если слово, представляющее раскрываемую переменную, заключено в двойные -кавычки или нет».

Вы также используете echoс расширением переменных, происходящим в той же строке; вы можете получить более четкие результаты, если будете использовать что-то более настраиваемое, например printf(, как Кусалананда ), или как:

$ printf -- '->%s<-\n' "${ape[@]}"
->Apple Banana<-
->Emacs Window<-
->Panda Bamboo Nature<-

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

printf -- '->%s<-\n' "Apple Banana" "Emacs Window" "Panda Bamboo Nature"

В отличие от версии без кавычек:

$ printf -- '->%s<-\n' ${ape[@]}
->Apple<-
->Banana<-
->Emacs<-
->Window<-
->Panda<-
->Bamboo<-
->Nature<-

... где промежуточные значения:

printf -- '->%s<-\n' Apple Banana Emacs Window Panda Bamboo Nature

... который точно показывает, до чего были расширены элементы. В первом случае переменная заключена в кавычки, поэтому дальнейшее разбиение на слова -не происходит, и вы получаете обратно три элемента. Во втором случае каждый из этих трех элементов также подвергается разбиению на слова, поэтому printfвидит для печати семь элементов.

«Длина» массива обычно представляет собой количество элементов, которые вы сгенерировали с помощью синтаксиса ${#ape[@]}. Использование ${#ape}запрашивает у bash длину первого элемента:

Referencing an array variable without a subscript is equivalent to referencing with a subscript of 0

, вот почему вы получаете эти разные значения.

0
28.01.2020, 02:18

Теги

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