使用 sed 替换关联 bash 数组中的匹配值
Use sed to replace matched value from associative bash 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[]}/g'
# result: ${MONTHS[01]}
# break out of the single quotes
sed 's/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/'"${MONTHS[]}"'/g'
# result:
# use double quotes
sed "s/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/${MONTHS[]}/g"
# result:
# use double quotes *and* a hardcoded example
sed "s/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/${MONTHS[]}, ${MONTHS[01]}/g"
# result: , Jan
是否可以使用 sed
中的匹配组值作为替换中的数组索引?
注意: 我有意避免使用 date
函数,因为它的应用可能超出实际日期;但是,我绝对愿意接受其他方法,例如 awk
.
首先,您可以将关联数组转换为按顺序包含月份名称的字符串
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-", , mon[+0]); for (i=3; i < NF; i++) { printf("%s-", $i); } printf("%s\n", $NF);}'
也就是把包含月份的字符串存入你一开始拆分的变量中,然后替换第二个字段打印所有。
我建议 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="-"} {=mths[+0]} 1' <<< "$s"
输出:
2016-Jan-20T08:15:32.398242-05:00
首先从您的数组生成 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"
如果必须 sed...这是使用 t 命令的 "brute force" 答案:
#! /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
我正在使用 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[]}/g'
# result: ${MONTHS[01]}
# break out of the single quotes
sed 's/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/'"${MONTHS[]}"'/g'
# result:
# use double quotes
sed "s/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/${MONTHS[]}/g"
# result:
# use double quotes *and* a hardcoded example
sed "s/^[0-9]\{4\}-\([0-9]\{2\}\)-.*/${MONTHS[]}, ${MONTHS[01]}/g"
# result: , Jan
是否可以使用 sed
中的匹配组值作为替换中的数组索引?
注意: 我有意避免使用 date
函数,因为它的应用可能超出实际日期;但是,我绝对愿意接受其他方法,例如 awk
.
首先,您可以将关联数组转换为按顺序包含月份名称的字符串
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-", , mon[+0]); for (i=3; i < NF; i++) { printf("%s-", $i); } printf("%s\n", $NF);}'
也就是把包含月份的字符串存入你一开始拆分的变量中,然后替换第二个字段打印所有。
我建议 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="-"} {=mths[+0]} 1' <<< "$s"
输出:
2016-Jan-20T08:15:32.398242-05:00
首先从您的数组生成 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"
如果必须 sed...这是使用 t 命令的 "brute force" 答案:
#! /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