You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle数据库XML数据导出为CSV后Shell脚本读取异常求助

Oracle导出XML到CSV后,Shell脚本无法正确解析多行XML内容

我需要从Oracle数据库提取XML数据并导出为CSV格式,再通过Shell脚本读取这些数据,但目前脚本的输出完全不符合预期,恳请大家帮忙排查问题。

我的SQL查询语句

select routeset_name as routeset_name, Trim(Replace(a.XML_MSG.getStringVal(),' ','')) as xml_msg from ums_lrt_staging_routeset_xml_msg a

我的Shell脚本

while IFS="," read -r ROUTESET_NAME XML_MSG
do
    echo "ROUTESET_NAME: $ROUTESET_NAME"
    echo "XML_MSG: $XML_MSG"
    echo ""
done < <(tail RouteSets.csv)

当前RouteSets.csv内容

ROUTESET_NAME,XML_MSG
test,<?xml version="1.0" standalone='yes'?>
<localRoutes>
<route>
<user type="string">100</user>
<next type="regex">100</next>
</route>
<emsVersion>
<version>1</version>
</emsVersion>
</localRoutes>

实际输出结果

ROUTESET_NAME: XML_MSG
XML_MSG:
ROUTESET_NAME: "<pre><?xml version=""1.0"" standalone='yes'?>"
XML_MSG:
ROUTESET_NAME:
XML_MSG:
ROUTESET_NAME:
XML_MSG:
ROUTESET_NAME:
XML_MSG:
ROUTESET_NAME:
XML_MSG:
ROUTESET_NAME:
XML_MSG:

期望输出结果

ROUTESET_NAME: test
XML_MSG:<?xml version="1.0" standalone='yes'?><localRoutes><route><user type="string">100</user><next type="regex">100</next></route><emsVersion><version>1</version></emsVersion></localRoutes>

已尝试的解决方法

  • 使用getStringValue方法将XML转换为字符串,但无效;
  • 使用Trim方法去除首尾空格,无效;
  • 使用Replace方法去除标签间空格,无效。

问题根源分析

你的核心问题出在CSV格式不规范和Shell读取逻辑不匹配:

  1. 导出的XML是多行格式化的,但CSV默认是每行一条记录,且字段内的换行需要用双引号包裹,否则Shell的read命令会把每一行XML都当成独立的记录处理;
  2. 你用tail RouteSets.csv没有跳过表头行,导致表头被当成一条记录读取;
  3. 即使去掉空格,XML的换行依然存在,无法让read把整个XML识别为单个字段。

解决方案

1. 修正SQL,生成规范的单行CSV

要让XML成为CSV的单个字段,需要把XML转成单行无格式字符串,并用双引号包裹(符合CSV规范)。推荐使用Oracle的XMLSERIALIZE函数直接生成无缩进的单行XML:

SELECT 
    routeset_name AS routeset_name,
    '"' || XMLSERIALIZE(CONTENT a.XML_MSG AS VARCHAR2(4000) NO INDENT) || '"' AS xml_msg 
FROM ums_lrt_staging_routeset_xml_msg a;
  • NO INDENT会去掉XML的所有缩进和换行,直接输出单行字符串;
  • 用双引号包裹XML字段,确保CSV解析器将其识别为单个字段。

如果无法使用XMLSERIALIZE,也可以手动去除换行符:

SELECT 
    routeset_name AS routeset_name,
    '"' || REPLACE(REPLACE(a.XML_MSG.getStringVal(), CHR(10), ''), CHR(13), '') || '"' AS xml_msg 
FROM ums_lrt_staging_routeset_xml_msg a;

这里CHR(10)是换行符,CHR(13)是回车符,双重替换确保XML完全单行。

2. 修正Shell脚本,正确读取CSV

现在CSV是规范格式了,我们可以用更可靠的方式读取,比如用awk(原生工具,无需额外安装)来处理带引号的字段:

awk -F ',' 'BEGIN {OFS=","} NR>1 {
    gsub(/^"|"$/, "", $2)  # 去掉XML字段前后的双引号
    print "ROUTESET_NAME: " $1
    print "XML_MSG:" $2
    print ""
}' RouteSets.csv
  • NR>1跳过表头行;
  • gsub去掉XML字段的首尾双引号,避免输出带引号的内容;
  • 直接输出你需要的格式。

如果坚持用while read循环,可以用以下方法(处理带引号的字段):

while IFS= read -r line
do
    # 跳过表头
    if [[ "$line" == ROUTESET_NAME* ]]; then
        continue
    fi
    # 拆分字段:第一个逗号前是ROUTESET_NAME,后面的是XML_MSG(包括引号)
    ROUTESET_NAME="${line%%,*}"
    XML_MSG="${line#*,}"
    # 去掉XML_MSG的首尾引号
    XML_MSG="${XML_MSG%\"}"
    XML_MSG="${XML_MSG#\"}"
    echo "ROUTESET_NAME: $ROUTESET_NAME"
    echo "XML_MSG:$XML_MSG"
    echo ""
done < RouteSets.csv

验证结果

执行修正后的SQL导出CSV后,再运行新的Shell脚本,就能得到你期望的输出了。

内容的提问来源于stack exchange,提问作者akt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 21:57:28