找出一个字符串是不是只包含 ASCII 字符
Posted
技术标签:
【中文标题】找出一个字符串是不是只包含 ASCII 字符【英文标题】:Find out if a string contains only ASCII characters找出一个字符串是否只包含 ASCII 字符 【发布时间】:2018-11-27 14:55:51 【问题描述】:我需要知道一个字符串是否只包含 ASCII 字符。到目前为止,我使用这个正则表达式:
DECLARE
str VARCHAR2(100) := 'xyz';
BEGIN
IF REGEXP_LIKE(str, '^[ -~]+$') THEN
DBMS_OUTPUT.PUT_LINE('Pure ASCII');
END IF;
END;
/
Pure ASCII
' '
和 ~
分别是第一个。 ASCII 中的最后一个字符。
问题是,此 REGEXP_LIKE 在某些 NLS 设置上失败:
ALTER SESSION SET NLS_SORT = 'GERMAN';
DECLARE
str VARCHAR2(100) := 'xyz';
BEGIN
IF REGEXP_LIKE(str, '^[ -~]+$') THEN
DBMS_OUTPUT.PUT_LINE('Pure ASCII');
END IF;
END;
/
ORA-12728: invalid range in regular expression
ORA-06512: at line 4
有人知道独立于当前用户 NLS 设置的解决方案吗?这种行为是故意的还是应该被视为错误?
【问题讨论】:
这个能用吗:IF (ASCIISTR(str) = str) THEN
?
[ -~]
是可打印的 ascii,但 ascii 确实是 7 位 [\x00-\x7F]
有趣的是,反斜杠似乎未能通过该测试; asciistr('\')
给出\005C
,大概是为了避免混淆,因为它在输出中具有特殊含义。
@sln, [\x20-\x7E]
也会引发 ORA-12728
@sln - 在 Oracle 的德语语言排序顺序中,字符 x20 比字符 x7E“更大”。 x7E 是#63,x20 是#66。完整的可打印 ASCII 字符范围是 x21 - x39。
【参考方案1】:
您可以使用TRANSLATE
来执行此操作。基本上,translate
去掉所有 ASCII 可打印字符(没有那么多),看看你还剩下什么。
这是一个执行此操作的查询:
WITH input ( p_string_to_test) AS (
SELECT 'This this string' FROM DUAL UNION ALL
SELECT 'Test this ' || CHR(7) || ' string too!' FROM DUAL UNION ALL
SELECT 'xxx' FROM DUAL)
SELECT p_string_to_test,
case when translate(p_string_to_test,
chr(0) || q'[ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz|~]',
chr(0)) is null then 'Yes' else 'No' END is_ascii
FROM input;
+-------------------------+----------+ | P_STRING_TO_TEST | IS_ASCII | +-------------------------+----------+ | This this string | Yes | | Test this string too! | No | | xxx | Yes | +-------------------------+----------+
【讨论】:
[:print:] 包括非 ascii 字符。【参考方案2】:可以使用上限为127
的ASCII
函数:
declare
str nvarchar2(100) := '\xyz~*-=)(/&%+$#£>|"éß';
a nvarchar2(1);
b number := 0;
begin
for i in 1..length(str)
loop
a := substrc(str,i,1);
b := greatest(ascii(a),b);
end loop;
if b < 128 then
dbms_output.put_line('String is composed of Pure ASCII characters');
else
dbms_output.put_line('String has non-ASCII characters');
end if;
end;
【讨论】:
【参考方案3】:我想我会选择这两个中的一个
IF CONVERT(str, 'US7ASCII') = str THEN
DBMS_OUTPUT.PUT_LINE('Pure ASCII');
END IF;
IF ASCIISTR(REPLACE(str, '\', '/')) = REPLACE(str, '\', '/') THEN
DBMS_OUTPUT.PUT_LINE('Pure ASCII');
END IF;
【讨论】:
那些将包括范围低端的不可打印字符,不是吗? @MatthewMcPeak,是的,但我的主要兴趣是找到像öäü
这样的特殊字符。不可打印的字符与我的情况无关。以上是关于找出一个字符串是不是只包含 ASCII 字符的主要内容,如果未能解决你的问题,请参考以下文章
仅包含 ASCII 字符的 UNICODE 字符串是不是总是等于 ASCII 字符串?