sed/awk批量替换XML行失败,如何按$time/$date条件替换为NaN?
解决批量替换XML中指定时间注释行数值的问题
看起来你在尝试批量修改XML文件中带有特定时间日期注释的行,把<v>标签里的数值替换成NaN,但之前的sed和awk命令都因为语法问题失败了。我来帮你梳理错误原因并给出正确的解决方案:
先分析你之前的错误
sed命令的问题
你写的sed命令缺少了替换命令前缀s,sed的替换语法是sed 's/匹配模式/替换内容/选项' 文件,而你直接写了匹配串和替换内容,导致sed把第一个字符<当成了未知命令,所以报错unknown command: '<'。另外,原内容中的/需要转义,否则会被当成sed的分隔符打断命令。
awk命令的问题
awk的正则表达式用/包裹,而你的匹配串里包含了/(比如注释里的/ 1594206000),没有转义成\/,导致awk解析正则时出现语法错误;另外,你用"来表示引号是没必要的,awk里直接用双引号或者单引号即可(注意shell的引号嵌套)。
正确的解决方案
方案1:用sed精准替换单条时间注释的行
如果只需要替换某一条特定时间注释的行,可以用sed的分组捕获来保留注释部分,只替换数值:
sed -i 's/\(<!-- 2020-07-06 16:45:00 WEST \/ 1594050300 --><row><v>\)[0-9.e+-]*\(<\/v><\/row>\)/\1NaN\2/' dump_teste.xml
- 解释:
\( ... \)用来捕获需要保留的部分:前面的注释和<row><v>,以及后面的</v></row>[0-9.e+-]*匹配科学计数法格式的数值(覆盖整数、小数、指数形式)\1和\2引用捕获的内容,中间替换成NaN
如果觉得转义/麻烦,可以换用其他分隔符(比如#),这样不需要转义:
sed -i 's#\(<!-- 2020-07-06 16:45:00 WEST / 1594050300 --><row><v>\)[0-9.e+-]*\(</v></row>\)#\1NaN\2#' dump_teste.xml
方案2:用awk处理单条或多条时间注释
awk处理带/的字符串更灵活,可以把要匹配的注释作为变量传入,避免转义:
# 单条注释替换 awk -v target_comment='<!-- 2020-07-06 16:45:00 WEST / 1594050300 -->' ' $0 ~ target_comment { sub(/<v>[0-9.e+-]*<\/v>/, "<v>NaN</v>") } 1 # 打印所有行 ' dump_teste.xml > tmp.xml && mv tmp.xml dump_teste.xml
如果要批量处理多条时间注释,可以把注释用|分隔成正则的“或”条件:
awk -v target_comments='<!-- 2020-07-06 16:45:00 WEST / 1594050300 -->|<!-- 2020-07-08 12:00:00 WEST / 1594206000 -->' ' $0 ~ target_comments { sub(/<v>[0-9.e+-]*<\/v>/, "<v>NaN</v>") } 1 ' dump_teste.xml > tmp.xml && mv tmp.xml dump_teste.xml
方案3:批量处理大量时间注释(从文件读取)
如果你有成百上千条时间注释需要处理,可以把所有注释放到一个文本文件(比如comments.txt),每行一条注释,然后用循环批量处理:
# comments.txt内容示例: # <!-- 2020-07-06 16:45:00 WEST / 1594050300 --> # <!-- 2020-07-08 12:00:00 WEST / 1594206000 --> while read -r comment; do sed -i "s#\(${comment}<row><v>\)[0-9.e+-]*\(</v></row>\)#\1NaN\2#" dump_teste.xml done < comments.txt
这个方法会逐行读取comments.txt里的注释,对XML文件进行批量替换。
内容的提问来源于stack exchange,提问作者SHEEN
相关产品推荐
相关产品推荐

