“Não é possível realocar” ao criar um arquivo?

0

Estou tentando criar uma planilha de excel com base em vários arquivos em uma raiz. Eu leio arquivos linha por linha e acrescento na folha final do excel.

Eu estou tentando este script de shell em arquivos pequenos e funcionou 100%, mas quando eu tento nos arquivos necessários (85MB por cada arquivo) eu recebo este erro:

(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)

Nota:

  • O parâmetro csv é a extensão do arquivo

  • Meu sistema operacional e versão: Unix AIX 7.1

Aqui está o script:

#!/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;
    
por Ahmed Samir 19.11.2015 / 10:59

1 resposta

0

Apenas algumas coisas sobre esse script, ignorando que é um script de shell que lida com XML.

  1. Ele lê cada arquivo na memória.
  2. Ele usa algumas construções que são "má prática".

Vamos consertar isso.

  • Primeiro, cada comando não precisa terminar com ; . O ; é usado se você colocar vários comandos em uma linha, como ls; echo "hello" .

  • As expansões variáveis também devem ser citadas em duplicidade. Consulte " Implicações de segurança do esquecimento para citar uma variável em shells bash / POSIX ". Por exemplo: Ext="$1" , XMLHeader >"$OutPutFileName" , etc.

  • for Vfile in $(ls | grep .$Ext) é melhor escrito for Vfile in ./*."$Ext" .

  • Em vez de fazer vários redirecionamentos em um loop, todos anexando ao mesmo arquivo, finalize o loop com done >>"$OutPutFileName" . Isso é mais eficiente.

  • VarRow='cat $Vfile' colocará o conteúdo de um arquivo de 85Mb em uma única variável e, em seguida, for Row in $(echo $VarRow ) fará um loop sobre as linhas, ou assim você espera. Em vez disso, faça while IFS= read -r Row; do ... done <"$Vfile" . Isto irá ler uma linha de cada vez. Em vez de armazenar o arquivo inteiro, você sempre armazena uma linha por vez. É provavelmente aí que você se depara com problemas de memória.

  • Em vez de VarCell='echo $VarRow' seguido por for Cell in $(echo $VarCell | sed "s/,/ /g") , basta fazer VarCell="${VarRow//,/ }" seguido por for Cell in $VarCell (isso é um pouco duvidoso, uma variável sem aspas que contém dados de entrada, sugestões de melhorias são bem-vindas)

  • Qualquer echo que produza dados variáveis, eu mudaria para printf com uma cadeia de formato de aspas simples seguida por expansões variáveis com aspas duplas. Por exemplo: echo "<Worksheet ss:Name=\"$Vfile\"><Table>" muda para printf '<Worksheet ss:Name="%s"><Table>\n' "$VFile" . Veja " Por que printf é melhor que echo? ".

  • Quando você deseja produzir uma cadeia longa (várias linhas), use um documento here. Dessa forma, você também não precisa se preocupar em escapar de citações.

por 09.01.2017 / 00:19