Bash echo输出含*,*的Oracle查询结果时双空格被转制表符问题
Bash调用sqlplus读取Oracle数据时空格被转制表符问题说明
复现准备
首先在Oracle数据库中创建测试表并插入测试数据,对应SQL如下:
CREATE TABLE spacetest ( col1 varchar2(20), col2 varchar2(100) ); INSERT INTO spacetest values('TEST','BETWEEN TWOSPACES'); commit;
测试数据中col2字段值为BETWEEN TWOSPACES,中间包含2个ASCII编码为32的空格字符,直接在数据库中查询时,双空格可正常保留。
用于复现问题的Bash测试脚本如下:
#!/bin/bash set -x lsout=$(sqlplus -S /NOLOG <<EOF set heading off termout off pagesize 0 echo off conn user/password@//localhost:1521/localdatabase SELECT * FROM spacetest; select COL1 || '*,*' || COL2 || '#@' combined FROM SPACETEST; select COL1 || '*,' || COL2 || '#@' combined FROM SPACETEST; select COL1 || ',*' || COL2 || '#@' combined FROM SPACETEST; select COL1 || '**' || COL2 || '#@' combined FROM SPACETEST; select COL1 || '°,#' || COL2 || '#@' combined FROM SPACETEST; select COL1 || '*#*' || COL2 || '#@' combined FROM SPACETEST; exit EOF ) echo "$lsout" | od -c echo done
异常表现
执行上述脚本后可观测到以下现象:
- 当查询结果拼接的分隔符包含
*,*或#,#时,字符串中原有的双空格会被转换为制表符 - 该异常不会在数据库端出现,数据库返回的结果始终保留原始双空格
测试环境版本
-- Oracle数据库版本查询 SELECT * FROM v$version; -- 返回结果 Oracle Database 19c Enterprise Edition Release 19.0.0.0.0
# Bash版本查询 echo "${BASH_VERSION}" # 返回结果 4.2.46(2)-release
异常产生原因
该异常和Bash解释器无关,问题出在sqlplus客户端的默认输出配置:
- sqlplus默认开启列对齐优化,会自动将输出内容中的连续空格替换为制表符,在减少输出字符数的同时实现列对齐效果。当拼接的分隔符包含
*,*这类会被sqlplus识别为多列边界的字符组合时,就会触发这个自动格式化逻辑,把字段值内部原本的连续双空格替换为制表符。 - 整个字符替换动作发生在sqlplus客户端输出环节,数据库端返回的原始结果始终是正确的,Bash只是原样接收了sqlplus输出的内容,没有做任何字符修改。
验证与修复方式:在sqlplus的会话初始化参数中添加
set tab off配置,关闭自动用制表符填充对齐的功能,再次执行脚本即可看到原始的连续双空格被完整保留,不会再出现异常转换。
内容的提问来源于stack exchange,提问作者Baker
相关产品推荐
相关产品推荐

