SadServers解説#11 "Minneapolis": Break a CSV file
問題概要
シナリオ
CSVファイルを分割する
問題詳細
home/admin/
ディレクトリにあるCSVファイルdata\.csv
を、サイズがほぼ同じになるように正確に10個の小さなファイルdata-00.csv
、data-01.csv
、…data-09.csv
に分割してください。すべてのファイルは、data\.csv
と同じヘッダー(カラム名が書かれた1行目)を持つ必要があります。どの小さなファイルも32KBを超えてはいけません。
※ファイルが行の途中で区切られても構いません(つまり、ファイルは改行で区切らず、どこでも分割して構いません)。生成されるファイルは、完全なCSVファイルである必要はありません。
解決判定
Check My Solution
ボタンをクリックしてください。
解決判定をするスクリプト/home/admin/agent/check.sh
は閲覧・実行可能です。
問題解決の方針
【表示する】
今回は、ファイルの分割などの方法が問われています。
均等に分割しなくてもよい代わりに、ヘッダーをそろえる必要があるそうです。
題意を満たすファイルを作成するためにはどういった段取りが必要でしょうか。
解決の手順を表示する
-
data\.csv
を分割する - 分割したファイルの1行目に
data\.csv
の1行目を挿入する
先にdata\.csv
から1行目を切り出し、残りの部分を10分割してから1行目を挿入することで、各ファイルのサイズを均等にすることができます。別解にその解法を載せています。
ヒント
一部、SadServers公式のヒントを改変しています。
ヒント1
ファイルを分割するコマンドはsplit
です。
実行コマンド
まずはhelpを見てみます。
$ split --help
Usage: split [OPTION]... [FILE [PREFIX]]
Output pieces of FILE to PREFIXaa, PREFIXab, ...;
default size is 1000 lines, and default PREFIX is 'x'.
With no FILE, or when FILE is -, read standard input.
Mandatory arguments to long options are mandatory for short options too.
-a, --suffix-length=N generate suffixes of length N (default 2)
--additional-suffix=SUFFIX append an additional SUFFIX to file names
-b, --bytes=SIZE put SIZE bytes per output file
-C, --line-bytes=SIZE put at most SIZE bytes of records per output file
-d use numeric suffixes starting at 0, not alphabetic
--numeric-suffixes[=FROM] same as -d, but allow setting the start value
-x use hex suffixes starting at 0, not alphabetic
--hex-suffixes[=FROM] same as -x, but allow setting the start value
-e, --elide-empty-files do not generate empty output files with '-n'
--filter=COMMAND write to shell COMMAND; file name is $FILE
-l, --lines=NUMBER put NUMBER lines/records per output file
-n, --number=CHUNKS generate CHUNKS output files; see explanation below
-t, --separator=SEP use SEP instead of newline as the record separator;
'\0' (zero) specifies the NUL character
-u, --unbuffered immediately copy input to output with '-n r/...'
--verbose print a diagnostic just before each
output file is opened
--help display this help and exit
--version output version information and exit
The SIZE argument is an integer and optional unit (example: 10K is 10*1024).
Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers of 1000).
Binary prefixes can be used, too: KiB=K, MiB=M, and so on.
CHUNKS may be:
N split into N files based on size of input
K/N output Kth of N to stdout
l/N split into N files without splitting lines/records
l/K/N output Kth of N to stdout without splitting lines/records
r/N like 'l' but use round robin distribution
r/K/N likewise but only output Kth of N to stdout
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/split>
or available locally via: info '(coreutils) split invocation'
…だそうなので、-n 10
オプションで10ファイルに分割しましょう。
$ split -n 10 data.csv
$ ls -l
total 640
-rw-r--r-- 1 admin admin 422 Jul 20 16:49 README.txt
drwxr-xr-x 2 admin root 4096 Jul 20 16:49 agent
-rw-r--r-- 1 admin admin 312715 Jul 20 16:49 data.csv
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xaa
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xab
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xac
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xad
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xae
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xaf
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xag
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xah
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xai
-rw-r--r-- 1 admin admin 31276 Oct 13 06:02 xaj
xaa
~xaj
の10つのファイルに分割されたようです。
ヒント2
分割したファイルの1行目に、data.csvの1行目を挿入しましょう。
まずは、data.csvの1行目を抽出して、header
というファイルを作成しましょう。
実行コマンド
$ head -1 data.csv > header
$ ls -l
total 640
-rw-r--r-- 1 admin admin 422 Jul 20 16:49 README.txt
drwxr-xr-x 2 admin root 4096 Jul 20 16:49 agent
-rw-r--r-- 1 admin admin 312715 Jul 20 16:49 data.csv
-rw-r--r-- 1 admin admin 372 Oct 13 06:05 header
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xaa
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xab
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xac
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xad
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xae
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xaf
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xag
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xah
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xai
-rw-r--r-- 1 admin admin 31276 Oct 13 06:02 xaj
header
というファイルが作成できました。
中身が心配なら、元のファイルとdiff
を取るなどしてください。
続けて、分割したファイルの1行目にheader
を挿入します。
実行コマンド2
一つ目のファイルには、すでにヘッダーが含まれているため、header
ファイルと結合する必要がないことに注意してください。
$ cat xaa > data-00.csv
$ cat header xab > data-01.csv
$ cat header xac > data-02.csv
$ cat header xad > data-03.csv
$ cat header xae > data-04.csv
$ cat header xaf > data-05.csv
$ cat header xag > data-06.csv
$ cat header xah > data-07.csv
$ cat header xai > data-08.csv
$ cat header xaj > data-09.csv
$ ls -l
total 1280
-rw-r--r-- 1 admin admin 422 Jul 20 16:49 README.txt
drwxr-xr-x 2 admin root 4096 Jul 20 16:49 agent
-rw-r--r-- 1 admin admin 312715 Jul 20 16:49 data.csv
-rw-r--r-- 1 admin admin 31271 Oct 13 06:09 data-00.csv
-rw-r--r-- 1 admin admin 31643 Oct 13 06:09 data-01.csv
-rw-r--r-- 1 admin admin 31643 Oct 13 06:09 data-02.csv
-rw-r--r-- 1 admin admin 31643 Oct 13 06:09 data-03.csv
-rw-r--r-- 1 admin admin 31643 Oct 13 06:09 data-04.csv
-rw-r--r-- 1 admin admin 31643 Oct 13 06:09 data-05.csv
-rw-r--r-- 1 admin admin 31643 Oct 13 06:09 data-06.csv
-rw-r--r-- 1 admin admin 31643 Oct 13 06:09 data-07.csv
-rw-r--r-- 1 admin admin 31643 Oct 13 06:09 data-08.csv
-rw-r--r-- 1 admin admin 31648 Oct 13 06:09 data-09.csv
-rw-r--r-- 1 admin admin 372 Oct 13 06:05 header
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xaa
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xab
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xac
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xad
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xae
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xaf
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xag
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xah
-rw-r--r-- 1 admin admin 31271 Oct 13 06:02 xai
-rw-r--r-- 1 admin admin 31276 Oct 13 06:02 xaj
各ファイルが32KBを下回っていることが確認できます。
Check My Solution
ボタンをクリックしてクリアです!
補足:headerの挿入のイメージ図
別解
先にdata.csv
から1行目を切り出し、残りの部分を10分割してから1行目を挿入します。
これにより、各ファイルのサイズを均等にすることができます。
実行コマンド
ファイルの結合をシェルで行うため、xa, xb,...
ではなく01, 02,...
と採番されるように、-d
オプションを使用しています。
$ head -n 1 data.csv > header
$ tail -n +2 data.csv > body
$ cat header body > test #想定通りに分割できていることを確認
$ diff data.csv test
$
$ ls -l
total 936
-rw-r--r-- 1 admin admin 422 Jul 20 16:49 README.txt
drwxr-xr-x 2 admin root 4096 Jul 20 16:49 agent
-rw-r--r-- 1 admin admin 312343 Oct 13 07:30 body
-rw-r--r-- 1 admin admin 312715 Jul 20 16:49 data.csv
-rw-r--r-- 1 admin admin 372 Oct 13 07:28 header
-rw-r--r-- 1 admin admin 312715 Oct 13 07:30 test
$
$ split -n 10 -d body
$
$ ls -l
total 1256
-rw-r--r-- 1 admin admin 422 Jul 20 16:49 README.txt
drwxr-xr-x 2 admin root 4096 Jul 20 16:49 agent
-rw-r--r-- 1 admin admin 312343 Oct 13 07:30 body
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x00
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x01
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x02
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x03
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x04
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x05
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x06
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x07
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x08
-rw-r--r-- 1 admin admin 31237 Oct 13 07:31 x09
-rw-r--r-- 1 admin admin 312715 Jul 20 16:49 data.csv
-rw-r--r-- 1 admin admin 372 Oct 13 07:28 header
-rw-r--r-- 1 admin admin 312715 Oct 13 07:30 test
$
$ for i in {0..9}; do cat header x0$i > data-0$i.csv; done
$
$ ls -l
total 1576
-rw-r--r-- 1 admin admin 422 Jul 20 16:49 README.txt
drwxr-xr-x 2 admin root 4096 Jul 20 16:49 agent
-rw-r--r-- 1 admin admin 312343 Oct 13 07:30 body
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x00
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x01
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x02
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x03
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x04
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x05
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x06
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x07
-rw-r--r-- 1 admin admin 31234 Oct 13 07:31 x08
-rw-r--r-- 1 admin admin 31237 Oct 13 07:31 x09
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-00.csv
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-01.csv
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-02.csv
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-03.csv
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-04.csv
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-05.csv
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-06.csv
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-07.csv
-rw-r--r-- 1 admin admin 31606 Oct 13 07:32 data-08.csv
-rw-r--r-- 1 admin admin 31609 Oct 13 07:32 data-09.csv
-rw-r--r-- 1 admin admin 312715 Jul 20 16:49 data.csv
-rw-r--r-- 1 admin admin 372 Oct 13 07:28 header
-rw-r--r-- 1 admin admin 312715 Oct 13 07:30 test
$ ./agent/check.sh
OK
問題一覧はこちら
Discussion