创建文件时“无法重新分配”?

创建文件时“无法重新分配”?

我正在尝试根据根目录上的多个文件创建 Excel 工作表。我逐行读取文件并附加到最​​终的 Excel 工作表中。

我正在小文件上尝试这个 shell 脚本,它运行 100%,但是当我在所需的文件(每个文件 85MB)上尝试它时,我收到此错误:

(dsadm@DEVDS) /EDWH/XML/Must # XML.sh csv excel_outputfilename
./XML.sh: line 41: fallocate: command not found
./XML.sh: xmalloc: cannot allocate 172035663 bytes (0 bytes allocated)
./XML.sh: xrealloc: cannot reallocate 86013568 bytes (0 bytes allocated)
./XML.sh: xrealloc: cannot reallocate 86021888 bytes (0 bytes allocated)

笔记:

  • 参数csv为文件扩展名

  • 我的操作系统和版本:Unix AIX 7.1

这是脚本:

#!/usr/bin/bash  

#Files Extension#
Ext=$1

#OutPut File Name without extension ex: TEST#
OutPutFileName=$2.xls

function XMLHeader ()
{
     echo "<?xml version=\"1.0\"?>
    <Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"
     xmlns:o=\"urn:schemas-microsoft-com:office:office\"
     xmlns:x=\"urn:schemas-microsoft-com:office:excel\"
     xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"
     xmlns:html=\"http://www.w3.org/TR/REC-html40\">"
}

function SheetHeader ()
{
    echo "<Worksheet ss:Name=\"Sheet1\">
    <Table ss:ExpandedColumnCount=\"2\" ss:ExpandedRowCount=\"2\" x:FullColumns=\"1\" x:FullRows=\"1\">
    <Row><Cell><Data ss:Type=\"String\">"
}

function SheetFooter ()
{
    echo "</Data></Cell></Row></Table>
    </Worksheet>"
}

function XMLFooter ()
{
    echo "</Workbook>"
}

####################################################################################

cd /EDWH/Samir/XML/Must;

fallocate -l 1G $OutPutFileName

XMLHeader > $OutPutFileName;

# loop on the exists files to build Worksheet per each file 
for Vfile in $(ls | grep .$Ext); 
do
    echo "<Worksheet ss:Name=\"$Vfile\"><Table>" >> $OutPutFileName

    ### loop to write the Row 
        VarRow=`cat $Vfile`
        for Row in $(echo $VarRow )
        do

            echo "<Row>" >> $OutPutFileName

                ### loop to write the cells 
                VarCell=`echo $VarRow`
                for Cell in $(echo $VarCell | sed "s/,/ /g")
                do
                    echo "<Cell><Data ss:Type=\"String\">$Cell</Data></Cell>" >> $OutPutFileName
                done

            echo "</Row>" >> $OutPutFileName

        done

    echo "</Table></Worksheet>" >> $OutPutFileName

done    


echo "</Workbook>" >> $OutPutFileName   

####################################################################################

exit;

答案1

仅介绍有关此脚本的一些信息,忽略它是处理 XML 的 shell 脚本。

  1. 它将每个文件读入内存。
  2. 它使用了一些“不好的做法”的结构。

让我们解决这个问题。

  • 首先,每个命令不需要以;.如果;您将多个命令放在一行上,例如ls; echo "hello".

  • 变量扩展应始终用双引号引起来。看 ”忘记在 bash/POSIX shell 中引用变量的安全隐患”。例如:Ext="$1"XMLHeader >"$OutPutFileName"等。

  • for Vfile in $(ls | grep .$Ext)写得比较好for Vfile in ./*."$Ext"

  • 不要在循环中执行多个重定向,将所有重定向都附加到同一文件,而是以done >>"$OutPutFileName".这样效率更高。

  • VarRow=`cat $Vfile`会将 85Mb 文件的内容放入单个变量中,然后for Row in $(echo $VarRow )循环遍历行,或者您希望如此。相反,做while IFS= read -r Row; do ... done <"$Vfile".这将一次读取一行。您一次只存储一行,而不是存储整个文件。这可能是您遇到内存问题的地方。

  • 而不是VarCell=`echo $VarRow`紧随其后for Cell in $(echo $VarCell | sed "s/,/ /g"),只需执行VarCell="${VarRow//,/ }"紧随其后for Cell in $VarCell (这感觉有点不确定,一个未加引号的变量保存输入数据,欢迎提出改进建议)

  • 任何echo输出变量数据的内容,我都会更改printf为单引号格式字符串,后跟双引号变量扩展。例如:echo "<Worksheet ss:Name=\"$Vfile\"><Table>"更改为printf '<Worksheet ss:Name="%s"><Table>\n' "$VFile".看 ”为什么 printf 比 echo 更好?”。

  • 当您想要输出长字符串(几行)时,请使用此处文档。这样您就不必担心转义引号。

相关内容