使用sed替换关联bash数组中的匹配值

时间:2016-01-20 15:46:45

标签: regex bash replace sed associative-array

我使用sed重新格式化输入字符串,其中一部分我想用不同的字符串替换。

输入字符串是格式为的日期:

%Y-%m-%dT%H:%M:%S.%N%:z
Example:
2016-01-20T08:15:32.398242-05:00

我的目标是使用01等字符串表示替换上例中的Jan

我已经定义了以下要使用的数组:

declare -A MONTHS=([01]="Jan" [02]="Feb" [03]="Mar" [04]="Apr" [05]="May" [06]="Jun" [07]="Jul" [08]="Aug" [09]="Sep" [10]="Oct" [11]="Nov" [12]="Dec")

我似乎不能让sed使用匹配组的值作为MONTHS数组的索引。

我尝试过的事情:

# straightforward sed approach
sed 's/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/${MONTHS[\1]}/g'
# result: ${MONTHS[01]}

# break out of the single quotes
sed 's/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/'"${MONTHS[\1]}"'/g'
# result: 

# use double quotes
sed "s/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/${MONTHS[\1]}/g"
# result: 

# use double quotes *and* a hardcoded example
sed "s/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/${MONTHS[\1]}, ${MONTHS[01]}/g"
# result: , Jan

是否可以使用sed中的匹配组值作为替换中的数组索引?

注意:我故意避免使用date功能,因为这可能超出实际日期;但是,我绝对愿意采用其他方法,例如awk

4 个答案:

答案 0 :(得分:2)

我建议将此awk作为替代方案:

s='2016-01-20T08:15:32.398242-05:00'

awk -v ms='Jan:Feb:Mar:Apr:May:Jun:Jul:Aug:Sep:Oct:Nov:Dec' 'BEGIN{
   split(ms, mths, ":"); FS=OFS="-"} {$2=mths[$2+0]} 1' <<< "$s"

<强>输出:

2016-Jan-20T08:15:32.398242-05:00

答案 1 :(得分:1)

首先,您可以将关联数组转换为按顺序包含月份名称的字符串

monstr=$(for k in "${!MONTHS[@]}"; do echo $k; done | sort | while read mon; do echo ${MONTHS[$mon]}; done)

然后,使用awk来完成繁重的工作

awk -F- -v monstr="$monstr" 'BEGIN { split(monstr, mon, " "); } { printf("%s-%s-", $1, mon[$2+0]); for (i=3; i < NF; i++) { printf("%s-", $i); } printf("%s\n", $NF);}'

也就是说,将包含月份的字符串存储在您在开头拆分的变量中,然后替换第二个字段并打印全部。

答案 2 :(得分:0)

首先从您的数组生成sed脚本,然后执行它。

免责声明:不确定我在以下代码中正确使用了bash数组。也不确定报价和逃避。

for k in $(seq -w 1 12) ; do
    echo 's/^[0-9]\{4\}-'"$k-.*/${MONTHS[$k]}/;"
done | sed -f - your_file

或者只使用bash

IFS=- read year mon rest <<<"$string"
string="$year ${MONTHS[$mon]} $rest"

答案 3 :(得分:0)

如果必须是sed ......这是使用 t 命令的“暴力”答案:

#! /bin/sed -f
s/-01-/-Jan-/; tx
s/-02-/-Feb-/; tx
s/-03-/-Mar-/; tx
s/-04-/-Apr-/; tx
s/-05-/-May-/; tx
s/-06-/-Jun-/; tx
s/-07-/-Jul-/; tx
s/-08-/-Aug-/; tx
s/-09-/-Sep-/; tx
s/-10-/-Oct-/; tx
s/-11-/-Nov-/; tx
s/-12-/-Dec-/; tx
:x