N個の行を持つことができるデータファイルがあります。各行は、スペースで区切られたM個の要素で構成されています。現在、各行を複数のセグメントに分割したいと思います。つまり、セグメント数が3であると仮定すると、元のファイルは3つのファイルに分割され、各ファイルにはN行があり、各行にはM / 3要素があります。 C ++またはJavaプログラムを書くことに加えて、Unix / Linuxでこれを行うための効率的な方法はありますか?
答え1
これは同じファイル内のさまざまな数のフィールドを満たし、最後のセグメントは部分的にのみ埋められます。つまり、指定されたより少ない数のフィールドがあります (セグメントごと)。
ただし、行のフィールド数によって指定された数より少ないセグメントが生成される場合、そのセグメントの出力ファイルには何も書き込まれません。
awk -v 'ncol=5' -v 'pfix=file' '{
fldn = 0
sfix = 1
segs = NF/ncol
# round up if number of field is not evenly divisible by number of columns
segs = (segs == int(segs)) ?segs :int(segs)+1
while (fldn != NF) {
fmod = (++fldn) % ncol
printf "%s%s", dlim, $(fldn) >> pfix sfix
if (fmod == 1 ) { dlim = " " }
if ((fmod==0 ) || (fldn==NF)) {
printf "\n" >> pfix sfix
dlim = ""; sfix++
}
}
}' infile
答え2
ファイルがきれいな場合は、標準アプリを使用することをお勧めしますcut
cut
あなたが知る必要がある少なくとも3つの兆候があります
- -d区切り文字を定義します(TABがデフォルト値です)。
- -f フィールドの選択
- -c文字範囲の選択
オプションで、-d -f または -c の組み合わせを使用できます。ファイルがタブで区切られていないが空白できれいに区切られている場合にできること
cut -d' ' -f1-3
最初の3つの列を選択します。
文字 25 から 36 の間にある列 4 を選択するには、次のようにします。
cut -c25-36
答え3
これはあなたが望むものですか?
awk '{ print $1 $2 $3 > file1; print $4 $5 $6 > file2; print $7 $8 $9 > file3 }' originalfile
それとももう少し多様な機能が欲しいですか?
awk -v 'n=3' -v 'prefix=pref' '{
for (i = 0; i < n; i++) {
for (j = 0; j < NF / n; j++) {
printf("%s ", $(i + j + 1)) > prefix i
}
printf("\n") > prefix i
}
}' originalfile
注:これは、すべての行に同じ数の列があるという前提に依存します。
答え4
sep_file.ksh
#!/bin/ksh
FILENAME=$1
SEG=$2
SEG_NO=1
while [[ $SEG_NO -le $SEG ]]
do
awk '{CL=NF/'"$SEG"';CL=(CL==int(CL)?CL:int(CL)+1);LS=(('"$SEG_NO"'-1)*CL)+1;LE=LS+CL-1;if(LE>NF)LE=NF;for(i=LS;i<=LE;i++)printf("%s ",$i);printf("\n")}' $FILENAME > ${FILENAME}_$SEG_NO
SEG_NO=`echo "$SEG_NO + 1"|bc`
done
使用法:./sep_file.ksh <file_name_to_read> <no_of_segments>