
ルートディレクトリにある複数のファイルに基づいてExcelシートを作成しようとしています。ファイルを1行ずつ読み、最終的なExcelシートに追加します。
このシェルスクリプトを小さなファイルで使用しようとしていますが、100%実行されますが、必要なファイル(それぞれ85 MB)に使用すると、次のエラーが発生します。
(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行に複数のコマンドを入力した場合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"
これは一度に1行ずつ読みます。ファイル全体ではなく、一度に1行ずつ保存します。おそらく、ここでメモリの問題が発生した可能性があります。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より優れているのですか?」。長い文字列(複数行)を出力するには、この文書を使用してください。これにより、引用符をエスケープすることを心配する必要はありません。