파일을 생성할 때 "재할당할 수 없습니다"?

파일을 생성할 때 "재할당할 수 없습니다"?

루트 디렉터리에 있는 여러 파일을 기반으로 Excel 시트를 만들려고 합니다. 파일을 한 줄씩 읽고 최종 Excel 시트에 추가합니다.

이 셸 스크립트를 작은 파일에 사용하려고 하는데 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을 처리하는 쉘 스크립트라는 점을 무시하고 이 스크립트에 대한 약간의 정보입니다.

  1. 각 파일을 메모리로 읽어옵니다.
  2. 이는 일부 "나쁜 관행" 구성을 사용합니다.

이 문제를 해결해 봅시다.

  • 첫째, 각 명령은 로 끝날 필요가 없습니다 ;. ;예를 들어 한 줄에 여러 명령을 입력 하면 ls; echo "hello".

  • 변수 확장은 항상 큰따옴표로 묶어야 합니다. 바라보다"bash/POSIX 쉘에서 변수를 인용하는 것을 잊어버리는 보안 위험". 예: 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예: .see" echo "<Worksheet ss:Name=\"$Vfile\"><Table>"로 변경printf '<Worksheet ss:Name="%s"><Table>\n' "$VFile"왜 printf가 echo보다 나은가요?".

  • 긴 문자열(여러 줄)을 출력하려면 이 문서를 사용하세요. 이렇게 하면 따옴표를 이스케이프하는 것에 대해 걱정할 필요가 없습니다.

관련 정보