Если вам нужна оболочка с лучшей поддержкой ассоциативных массивов, попробуйте zsh
.
В zsh
(где ассоциативные массивы были добавлены в 1998 г. по сравнению с 1993 г. для ksh93 и 2009 г. для bash), $var
или ${(v)var}
расширяется до (непустых) значений хеша, ${(k)var}
до (непустых) ключей (в том же порядке), и ${(kv)var}
как для ключей, так и для значений.
Чтобы сохранить пустые значения, как и для массивов, вам нужно заключить в кавычки и использовать флаг @
.
Таким образом, для вывода ключей и значений достаточно
printf '%s => %s\n' "${(@kv)var}"
Хотя для учета возможного пустого хеша вам следует сделать следующее:
(($#var)) && printf '%s => %s\n' "${(@kv)var}"
Также обратите внимание, что zsh использует гораздо более разумный и полезный синтаксис определения массива, чем ksh93
's (скопировано bash
):
typeset -A var
var=(k1 v1 k2 v2 '' empty '*' star)
Что значительно упрощает копирование или объединение ассоциативных массивов:
var2=("${(@kv)var1}")
var3+=("${(@kv)var2}")
var4=("${@kv)var4}" "${(@kv)var5}")
(вы не можете легко скопировать хэш без цикл с bash
, и обратите внимание, что bash
в настоящее время не поддерживает пустые ключи или ключи/значения с байтами NUL).
См. также zsh
функции сжатия массива, которые обычно требуются для работы с ассоциативными массивами:
keys=($(<keys.txt)) values=($(<values.txt))
hash=(${keys:^values})
Использование групп захвата и $ BASH_REMATCH
для извлечения битов строк:
for name in *.log.*; do
if [[ "$name" =~ \.([0-9]{4})_([0-9]{2})_([0-9]{2}) ]]; then
printf '%d-%d-%d from "%s"\n' \
"${BASH_REMATCH[1]}" \
"${BASH_REMATCH[2]}" \
"${BASH_REMATCH[3]}" \
"$name"
fi
done
Вывод:
2017-01-26 from "abcd.log.2017_01_26_23_30.0"
2017-01-26 from "abcd.log.2017_01_26_23_35.0"
2017-02-20 from "abcd.log.2017_02_20_23_10.0"
Если вам нужна строка даты в переменной:
for name in *.log.*; do
if [[ "$name" =~ \.([0-9]{4})_([0-9]{2})_([0-9]{2}) ]]; then
datestring="$( printf '%d-%d-%d' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" )"
printf '%s from "%s"\n' "$datestring" "$name"
fi
done
В ksh93
замените BASH_REMATCH
на .sh.match
.
Я бы использовал perl
и решайте это следующим образом:
#!/usr/bin/env perl
use strict;
use warnings;
while ( <> ) {
my ( @date ) = m/(\d{4})\D(\d{2})\D(\d{2})/;
my $date_str = join "-", @date;
print $date_str,"\n";
}
Он сопоставляет «4 цифры», «2 цифры», «2 цифры» и переформатирует их, чтобы они были разделены -
. Однако предполагается, что ваши номера расположены «правильно».