ksh变量可以接受的最大字符数是多少?

3
我正在尝试加载和解析一个非常大的文本文件,虽然加载不是问题,但有些行有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)

后续问题:有可能增加ksh变量可接受的最大字符数吗?


2
为什么不使用 wc -l 来计算文件中的行数?它不会受到 shell 的限制。我猜答案是“因为我需要进行其他处理,这些处理已被移除以便重现”。 - Jonathan Leffler
在我的Mac上,使用bash 3.2创建了一个没有任何换行符的4194304个字符的文件,然后bash完全忽略了这一行。我添加了一个单独的换行符,然后bash很高兴将整个文件都读入内存。因此,文件大小并不是硬性限制。你需要查看系统上有多少内存(我确定超过3 MiB),以及shell是否有许多巨大的变量占用了内存。 - Jonathan Leffler
你使用的是哪个操作系统和版本的ksh?你能够通过echo ${.sh.version}命令获取到值吗?如果可以,请在你的问题中包含这个信息。或者这可能是pdksh吗?祝大家好运。 - shellter
2
那就不要这样做!找到一些解决方案,不需要将整行加载到ksh变量中。 - me_and
1
@JonathanLeffler:你之所以能够使用echo输出如此大的字符串,是因为echo在Bash中是一个内置命令,因此ARG_MAX不适用于它。将echo "$(awk 'BEGIN { while (c++ < '"$(( $(getconf ARG_MAX) + 1 ))"') printf "=" }')" 与`/bin/echo "$(awk 'BEGIN { while (c++ < '"$(( $(getconf ARG_MAX) + 1 ))"') printf "=" }')"进行比较。尽管如此,我认为ARG_MAX与OP的问题无关。 - mklement0
显示剩余5条评论
2个回答

6

您使用的是什么操作系统和ksh版本?您可以执行echo ${.sh.version}命令并获取值吗?如果可以,请在您的问题中提供此信息。或者这可能是pdksh吗?

以下是一个测试,可以让您进入球场,假设您使用的是支持(( i++ ))数学计算的现代ksh:

#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 man页面将有一个名为LIMITS的部分,其中可能会显示类似于max-bytes 200MB, max-args 2048的内容。此信息可能在不同的部分中,它肯定有不同的标签和不同的值,我已经包含了它,或者可能根本不存在,因此需要上面的代码循环,请仔细查看,如果您找到这些信息的来源,请添加答案,或更新此答案。

bash 4.4的标准手册似乎没有提供此信息,而且难以找到ksh的文档。检查您的man ksh,希望您能找到有文档记录的限制。

IHTH


嗨,Shelter。假设有一个限制,是否有一种方法可以扩展这个限制?因为我确定我加载的记录不会停留在每行2M个字符上。是否有“while read line”的替代方法? - javapadawan

1
任何 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 < <(awk 'BEGIN { while (c++ < '"$(( $(getconf ARG_MAX) + 1 ))"') printf "=" }'); echo "${#line}" - mklement0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接