在 Shell 脚本中将字符串变量中的值转换为数组
Converting Values in a String Variable to Array in Shell Script
我有一个可能具有以下值组合的字符串变量 -
v="2020-01-2020-04,2020-11"
我希望将上述值转换为数组,如下所示-
array=(2020-01,2020-02,2020-03,2020-04,2020-11)
任何人都可以帮助我如何实现它并解释范围部分并相应地提取数组中的数据?
注意字符串中的值是 YYYY-MM 格式的月日
我已经尝试使用下面的代码根据“,”进行拆分,但无法处理范围-
IN="2020-01-2020-04,2020-11"
arrIN=(${IN//,/ })
echo ${arrIN[1]}
生成范围并将日期存储在 bash 数组中:
- 首先定义一个将月份加到日期的函数:
next_month() {
local y m
IFS='-' read y m <<< ""
if [ "$m" == 12 ]
then
m=1 y=$(( 10#$y + 1 ))
else
m=$(( 10#$m + 1 ))
fi
printf '%04d-%02d\n' "$y" "$m"
}
对于 GNU date
:
这可能是微不足道的
next_month() { date -d "-01 +1month" '+%Y-%m'; }
甚至 BSD date
next_month() { date -j -v '+1m' -f '%Y-%m' "" '+%Y-%m'; }
- 然后在填充数组的主循环中使用它:
v="2020-01-2020-04,2020-11"
array=()
for date in ${v//,/ }
do
[[ $date =~ ^([0-9]{4}-(0[1-9]|1[0-2]))(-([0-9]{4}-(0[1-9]|1[0-2])))?$ ]] || continue
inidate=${BASH_REMATCH[1]}
enddate=${BASH_REMATCH[4]:-$inidate}
until [ "$inidate" == "$enddate" ]
do
array+=( "$inidate" )
inidate=$(next_month "$inidate")
done
array+=( "$inidate" )
done
- 你会得到:
declare -p array
# declare -a array='([0]="2020-01" [1]="2020-02" [2]="2020-03" [3]="2020-04" [4]="2020-11")'
使用 bash
,请您尝试以下操作:
#!/bin/bash
v="2020-01-2020-04,2020-11"
IFS=, read -ra a <<< "$v" # split $v on comma(s) into an array a
for i in "${a[@]}"; do
if [[ $i =~ ^[0-9]{4}-[0-9]{2}$ ]]; then
array+=("$i") # single YYYY-MM
elif [[ $i =~ ^([0-9]{4})-([0-9]{2})-([0-9]{4})-([0-9]{2})$ ]]; then
# range of two YYYY-MM's
if (( 10#${BASH_REMATCH[1]} != 10#${BASH_REMATCH[3]} )); then
echo "the range of year not supported."
exit 1
else
for (( j = 10#${BASH_REMATCH[2]}; j <= ${BASH_REMATCH[4]}; j++ )); do
# expand the range of months
array+=( "$(printf "%04d-%02d" $((10#${BASH_REMATCH[1]})) "$j")" )
done
fi
fi
done
(IFS=","; echo "${array[*]}") # print the result
输出:
2020-01,2020-02,2020-03,2020-04,2020-11
我有一个可能具有以下值组合的字符串变量 -
v="2020-01-2020-04,2020-11"
我希望将上述值转换为数组,如下所示-
array=(2020-01,2020-02,2020-03,2020-04,2020-11)
任何人都可以帮助我如何实现它并解释范围部分并相应地提取数组中的数据?
注意字符串中的值是 YYYY-MM 格式的月日
我已经尝试使用下面的代码根据“,”进行拆分,但无法处理范围-
IN="2020-01-2020-04,2020-11"
arrIN=(${IN//,/ })
echo ${arrIN[1]}
生成范围并将日期存储在 bash 数组中:
- 首先定义一个将月份加到日期的函数:
next_month() {
local y m
IFS='-' read y m <<< ""
if [ "$m" == 12 ]
then
m=1 y=$(( 10#$y + 1 ))
else
m=$(( 10#$m + 1 ))
fi
printf '%04d-%02d\n' "$y" "$m"
}
对于 GNU date
:
next_month() { date -d "-01 +1month" '+%Y-%m'; }
甚至 BSD date
next_month() { date -j -v '+1m' -f '%Y-%m' "" '+%Y-%m'; }
- 然后在填充数组的主循环中使用它:
v="2020-01-2020-04,2020-11"
array=()
for date in ${v//,/ }
do
[[ $date =~ ^([0-9]{4}-(0[1-9]|1[0-2]))(-([0-9]{4}-(0[1-9]|1[0-2])))?$ ]] || continue
inidate=${BASH_REMATCH[1]}
enddate=${BASH_REMATCH[4]:-$inidate}
until [ "$inidate" == "$enddate" ]
do
array+=( "$inidate" )
inidate=$(next_month "$inidate")
done
array+=( "$inidate" )
done
- 你会得到:
declare -p array
# declare -a array='([0]="2020-01" [1]="2020-02" [2]="2020-03" [3]="2020-04" [4]="2020-11")'
使用 bash
,请您尝试以下操作:
#!/bin/bash
v="2020-01-2020-04,2020-11"
IFS=, read -ra a <<< "$v" # split $v on comma(s) into an array a
for i in "${a[@]}"; do
if [[ $i =~ ^[0-9]{4}-[0-9]{2}$ ]]; then
array+=("$i") # single YYYY-MM
elif [[ $i =~ ^([0-9]{4})-([0-9]{2})-([0-9]{4})-([0-9]{2})$ ]]; then
# range of two YYYY-MM's
if (( 10#${BASH_REMATCH[1]} != 10#${BASH_REMATCH[3]} )); then
echo "the range of year not supported."
exit 1
else
for (( j = 10#${BASH_REMATCH[2]}; j <= ${BASH_REMATCH[4]}; j++ )); do
# expand the range of months
array+=( "$(printf "%04d-%02d" $((10#${BASH_REMATCH[1]})) "$j")" )
done
fi
fi
done
(IFS=","; echo "${array[*]}") # print the result
输出:
2020-01,2020-02,2020-03,2020-04,2020-11