![파일을 생성할 때 "재할당할 수 없습니다"?](https://linux55.com/image/77700/%ED%8C%8C%EC%9D%BC%EC%9D%84%20%EC%83%9D%EC%84%B1%ED%95%A0%20%EB%95%8C%20%22%EC%9E%AC%ED%95%A0%EB%8B%B9%ED%95%A0%20%EC%88%98%20%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4%22%3F.png)
루트 디렉터리에 있는 여러 파일을 기반으로 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을 처리하는 쉘 스크립트라는 점을 무시하고 이 스크립트에 대한 약간의 정보입니다.
- 각 파일을 메모리로 읽어옵니다.
- 이는 일부 "나쁜 관행" 구성을 사용합니다.
이 문제를 해결해 봅시다.
첫째, 각 명령은 로 끝날 필요가 없습니다
;
.;
예를 들어 한 줄에 여러 명령을 입력 하면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보다 나은가요?".긴 문자열(여러 줄)을 출력하려면 이 문서를 사용하세요. 이렇게 하면 따옴표를 이스케이프하는 것에 대해 걱정할 필요가 없습니다.