我使用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
。
答案 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