Unix /usr/xpg4/bin/grep-q[^0-9]并非总是按预期工作

Unix /usr/xpg4/bin/grep-q[^0-9]并非总是按预期工作,unix,grep,ksh,Unix,Grep,Ksh,我有一个Unix ksh脚本,它已经在日常使用了很多年(由crontab在夜间启动)。最近,脚本中的一个函数表现出前所未有的不稳定。我尝试了各种方法来找出原因,但都没有成功 该函数验证输入字符串,该字符串应该是由10个数字字符组成的字符串。函数检查字符串长度是否为10,以及是否包含任何非数字字符: #/bin/ksh #职能: _有效吗_id(){ #接受一个参数,即正在测试的ID。 如果[[$(打印${1})-ne 10]]| |打印“$1”|/usr/xpg4/bin/grep-q[^0-9

我有一个Unix ksh脚本,它已经在日常使用了很多年(由crontab在夜间启动)。最近,脚本中的一个函数表现出前所未有的不稳定。我尝试了各种方法来找出原因,但都没有成功

该函数验证输入字符串,该字符串应该是由10个数字字符组成的字符串。函数检查字符串长度是否为10,以及是否包含任何非数字字符:

#/bin/ksh
#职能:
_有效吗_id(){
#接受一个参数,即正在测试的ID。
如果[[$(打印${1})-ne 10]]| |打印“$1”|/usr/xpg4/bin/grep-q[^0-9];则
返回1
其他的
返回0
fi
}
cat$input|文件|在读取行时;做
id=$(print$行| awk-F:'{print$5}')
#调用函数:
_id$id有效吗
stat=$?
如果[$stat-等式1]];然后
打印“ID$ID无效。请求被拒绝。\n”>$ERRLOG
持续
其他的
...
fi
完成
该函数的问题是,每天晚上,在数十个或数百个请求中,它都会发现几个请求中的ID无效。我目视检查了输入数据,发现所有“无效”ID实际上都是由10个数字字符组成的字符串。这个错误似乎是随机的,因为它只发生在一些请求中。然而,尽管被拒绝的请求会持续返回,但日复一日被选为无效的ID始终是相同的

我做了以下工作:

  • Unix计算机已运行近一年,因此可能需要刷新。系统管理员应我的请求重新启动计算机。但重新启动后问题仍然存在
  • 在命令提示下,我在函数中手动运行了完全相同的两个测试,在夜间发现无效的ID都是有效的
  • 我知道,手动或在脚本中调用相同的命令可能会有不同的行为。为了查看函数在脚本中的行为,上面的代码摘录是我运行以重现问题的小脚本。事实上,一些(尽管不是全部)在夜间被发现无效的ID也被小故障排除脚本发现无效
  • 然后,我修改了故障排除脚本,一次运行一个测试,发现是
    /usr/xpg4/bin/grep-q[^0-9]
    测试错误地发现某些ID包含非数字字符。嗯,ID都是数字字符,至少在视觉上是这样
  • 我检查了xpg4 grep命令文件(
    ls-l/usr/xpg4/bin/grep
    )是否有任何问题,以查看它是否最近放在那里。但是它的时间戳是2005年(这台机器运行Solaris 10)
  • 知道数据来自中央ERP系统,使用各种终端机器从不同位置执行数据输入,这些终端机器运行支持各种字符集和编码的各种可能的操作系统。ERP系统只允许他们这样做。但是,来自其他编码的字符是否可以直观地显示为数字字符,但编码值与Unix机器上的
    /usr/xpg4/bin/grep
    命令所期望的不同?我尝试了
    od
    (八进制转储)命令,但它对我帮助不大,因为我不熟悉它。也许我需要更多地了解
    od
    来解决这个问题

  • 我的临时工作是省略
    /usr/xpg4/bin/grep-q[^0-9]
    测试。但问题并没有得到解决。下一步我可以尝试什么?

    您的有效性测试功能恰好比它应该的更复杂。例如,为什么对
    ${1}
    使用带有
    print
    的命令替换?你为什么不直接使用
    ${1}
    ?其次,分叉grep来测试非数字是一个缓慢而昂贵的操作。那么这个等效函数呢,100%POSIX和惊人的速度:

    是否有效\u id(){
    #接受一个参数,即正在测试的ID。
    如果测试${1}-ne 10;那么
    返回1#ID长度不完全是10。
    fi
    每箱1元
    (*[!0-9]*)返回1;#ID包含非数字。
    (*)返回0;#ID正好是10位数字。
    以撒
    }
    
    或者更简单,如果你不介意重复你自己:

    是否有效\u id(){
    #接受一个参数,即正在测试的ID。
    每箱1元
    ([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])#10位数字。
    返回0;;
    (*)
    返回1;;
    以撒
    }
    

    这也避免了未加引号地使用
    grep
    模式,这在存在单字符文件名时很容易出错。这是否更有效?

    您的有效性测试功能恰巧比它应该的更复杂。例如,为什么对
    ${1}
    使用带有
    print
    的命令替换?你为什么不直接使用
    ${1}
    ?其次,分叉grep来测试非数字是一个缓慢而昂贵的操作。那么这个等效函数呢,100%POSIX和惊人的速度:

    是否有效\u id(){
    #接受一个参数,即正在测试的ID。
    如果测试${1}-ne 10;那么
    返回1#ID长度不完全是10。
    fi
    每箱1元
    (*[!0-9]*)返回1;#ID包含非数字。
    (*)返回0;#ID正好是10位数字。
    以撒
    }
    
    或者更简单,如果你不介意重复你自己:

    是否有效\u id(){
    #接受一个参数,即正在测试的ID。
    每箱1元
    ([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])#10位数字。
    返回0;;
    (*)
    返回1;;
    以撒
    }
    

    这也避免了未加引号地使用
    grep
    模式,这在存在单字符文件名时很容易出错。这是否更好?

    请给我们一个错误处理ID的实际示例。Ot