【问题标题】:What is the maximum number of characters that the ksh variable accepts?ksh 变量接受的最大字符数是多少?
【发布时间】:2012-12-31 12:49:30
【问题描述】:

我正在尝试加载和解析一个非常大的文本文件。虽然加载不是问题,但有一些特定的行在一行上有 2908778 个字符。

这导致我的脚本出错。

在下面的脚本中,我删除了所有逻辑并直接阅读行。 我还删除了所有有效行,只是将很长的行留在了一个文本文件中。运行时出现以下错误:

$ dowhiledebug.sh dump.txt
dowhiledebug.sh[6]: no space
Script Ended dump.txt

实际脚本:

 #!/bin/sh
 filename=$1
 count=1
 if [ -f ${filename} ]; then
    echo "after then"
    while read line;
            do
            echo "$count"
            count=$((count+1))
            done < $filename
 else
    echo "Could not open file $filename"
 fi
 echo "Script Ended $filename"

更新 (2013-01-17)

跟进问题:Is it possible to increase the maximum number of characters that ksh variable accepts?

【问题讨论】:

  • 为什么不使用wc -l 来计算文件中的行数?它不会有外壳的限制。我想答案是“因为我需要做其他处理,我已经删除了复制”。
  • 在我的带有bash 3.2 的Mac 上,我创建了一个包含4194304 个字符且根本没有换行符的文件,然后bash 完全忽略了该行。我添加了一个换行符,bash 很高兴将全部内容读入内存。因此,您的大小不是硬性限制。您需要查看系统上有多少内存(我敢肯定超过 3 MiB),以及 shell 是否有许多巨大的变量耗尽了内存。
  • 而且,FWIW,机器上 ARG_MAX 的 sysconf 值是 256 KiB,就像在答案中一样。我不认为该限制与 ARG_MAX 直接相关(不过,我承认,我能够将 4 MiB 字符串回显到 wc 有点惊讶)。这仍然在 Mac 上。
  • 那就别那么做了!为您的问题找到一些不需要您将整行加载到 ksh 变量中的解决方案。
  • @JonathanLeffler:你能够echo 这么大的字符串的原因是echo 是 Bash 中的 builtin,在这种情况下 ARG_MAX 不适用.比较 echo "$(awk 'BEGIN { while (c++ &lt; '"$(( $(getconf ARG_MAX) + 1 ))"') printf "=" }')"/bin/echo "$(awk 'BEGIN { while (c++ &lt; '"$(( $(getconf ARG_MAX) + 1 ))"') printf "=" }')"。也就是说,我也认为 ARG_MAX 与 OP 的问题无关。

标签: bash shell unix ksh


【解决方案1】:

什么操作系统和 ksh 版本?你能echo ${.sh.version} 得到一个值吗?如果是这样,请在上面的问题中包括。或者这可能是pdksh?

假设现代 ksh 支持 (( i++ )) 数学评估,这里有一个测试可以帮助您了解情况:

#100 char var
var=1234578901234456789012345678901234567890123456789012345789012344567890123456789012345678901234567890

$ while (( i++ < 10000 )) ;do  var="$var$var" ; print "i=$i\t" ${#var} ; done
i=1      200
i=2      400
i=3      800
i=4      1600
i=5      3200
i=6      6400
i=7      12800
i=8      25600
i=9      51200
i=10     102400
i=11     204800
i=12     409600
i=13     819200
i=14     1638400
i=15     3276800
i=16     6553600
i=17     13107200
i=18     26214400
i=19     52428800
i=20     104857600
i=21     209715200
i=22     419430400
-ksh: out of memory

$ print -- ${.sh.version}
Version JM 93t+ 2010-05-24

这只是可以支持的环境的总体大小。在处理命令行环境和程序名称后的“单词”时,单词的数量是有限制的,无论整体大小如何。

一些 shell 手册页会有一个 LIMITS 部分,可能会显示类似max-bytes 200MB, max-args 2048 的内容。这些信息可能在不同的部分,肯定会有不同的标签和不同的值,或者它可能根本不存在,因此上面的代码循环,所以仔细看看,如果你找到了这个信息的来源,或者添加这个 Q 的答案,或者更新这个。

bash 4.4 标准手册页似乎没有此信息,而且一直很难找到ksh 文档。检查您的man ksh,希望您能找到记录在案的限制。

IHTH

【讨论】:

  • 您好,避难所,假设有限制。有没有办法延长这个限制?因为我确定我正在加载的记录不会在每行 2M 个字符处停止?有没有“while read line”的替代方法?
【解决方案2】:

任何 shell 的限制是 C 命令行最大值的限制。这是一个小程序,可以为您从/usr/include/limits.h 中提取信息:

cpp <<HERE | tail -1
#include <limits.h>
ARG_MAX
HERE

我的给了我 (256 * 1024) 或 262144 个字符。

如果没有安装 C 编译器则不起作用,但可能是类似的限制。

【讨论】:

  • 虽然知道最大值是件好事。调用外部实用程序时的命令行长度(使用getconf ARG_MAX 更容易获得),此限制在此处适用,因为数据是从文件中读取的,而不是通过命令行;此外,read 是内置的 shell,而不是外部实用程序。以下ksh 命令读取比getconf ARG_MAX 大1 字节的行,成功:read line &lt; &lt;(awk 'BEGIN { while (c++ &lt; '"$(( $(getconf ARG_MAX) + 1 ))"') printf "=" }'); echo "${#line}"
猜你喜欢
  • 2014-05-09
  • 1970-01-01
  • 2020-10-06
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
相关资源
最近更新 更多