Revision | 07b7f3275530684a49ac71826f333a31de3f2535 (tree) |
---|---|
Time | 2019-10-11 14:37:37 |
Author | tfuruka1 <tfuruka1 at nifty dot com> |
Commiter | tfuruka1 |
重複行を排除するコマンドを登録しました。uniq で排除できないパターンを排除したかったので急遽作成しました。
@@ -0,0 +1,181 @@ | ||
1 | +/* $Id: main.c,v 1.1 2011/03/01 11:00:07 tfuruka1 Exp $ | |
2 | + * | |
3 | + * uniqコマンドで対応できなかったのでdedupを作る。 | |
4 | + * | |
5 | + */ | |
6 | +#include <stdio.h> | |
7 | +#include <stdarg.h> | |
8 | +#include <stdlib.h> | |
9 | +#include <string.h> | |
10 | +#include <malloc.h> | |
11 | +#include <fcntl.h> | |
12 | +#include <signal.h> | |
13 | +#include <io.h> | |
14 | +#include <fcntl.h> | |
15 | +#include <sys/types.h> | |
16 | +#include <sys/stat.h> | |
17 | + | |
18 | +#include <getopt.h> | |
19 | + | |
20 | +#define VERSION "0.1 ($Rev$)" | |
21 | + | |
22 | +#ifndef TRUE | |
23 | +# define TRUE 1 | |
24 | +# define FALSE 0 | |
25 | +#endif | |
26 | + | |
27 | +#define LINE_SIZE (1024) | |
28 | + | |
29 | +static void | |
30 | +showVersion() | |
31 | +{ | |
32 | + printf("dedup %s\n" | |
33 | + "Copyright (C) 2019 T.Furukawa.\n" | |
34 | + "重複行(複数行の繰返し行)の排除。\n", | |
35 | + VERSION); | |
36 | +} | |
37 | + | |
38 | +static void | |
39 | +showHelp() | |
40 | +{ | |
41 | + printf( | |
42 | + "使用法: dedup [オプション]\n" | |
43 | + "重複行を排除します。単行のみでなく複数行の繰返しも排除できます。\n" | |
44 | + "\n" | |
45 | + " -d, --deduplicate <行数> 繰返し行を指定します。\n" | |
46 | + " -h, --help この使い方を表示して終了\n" | |
47 | + " -v, --version バージョン情報を表示して終了\n" | |
48 | + "\n" | |
49 | + "行数に 1を指定した場合は uniq コマンドと同じ動作になります。" | |
50 | + "\n"); | |
51 | +} | |
52 | + | |
53 | +void | |
54 | +deduplicate(FILE *in, FILE *out, char *buf, int line) | |
55 | +{ | |
56 | + int i; | |
57 | + int b; | |
58 | + char *rb; | |
59 | + | |
60 | + /* 初期化 */ | |
61 | + for (i = 0; i < line * 2; i++) { | |
62 | + *(buf + i * LINE_SIZE) = '\0'; | |
63 | + } | |
64 | + | |
65 | + rb = buf + (line * 2 - 1) * LINE_SIZE; | |
66 | + while (fgets(rb, LINE_SIZE, in)) { | |
67 | + /* 先頭 n 行はチェックしない */ | |
68 | + for (i = 0; i < line; i++) { | |
69 | + if ('\0' == *(buf + i * LINE_SIZE)) { | |
70 | + fwrite(rb, strlen(buf + (line * 2 - 1) * LINE_SIZE), 1, out); | |
71 | + strcpy(buf + i * LINE_SIZE, rb); | |
72 | + break; | |
73 | + } | |
74 | + } | |
75 | + if (i < line) { | |
76 | + continue; | |
77 | + } | |
78 | + | |
79 | + /* データの詰め込み */ | |
80 | + for (i = line; i < line * 2 - 1; i++) { | |
81 | + if ('\0' == *(buf + i * LINE_SIZE)) { | |
82 | + strcpy(buf + i * LINE_SIZE, rb); | |
83 | + *rb = '\0'; | |
84 | + break; | |
85 | + } | |
86 | + } | |
87 | + | |
88 | + /* データの比較 */ | |
89 | + b = TRUE; | |
90 | + for (i = 0; i < line; i++) { | |
91 | + if ('\0' == *(buf + (line + i) * LINE_SIZE)) { | |
92 | + /* 一部一致(未だ判定できない) */ | |
93 | + break; | |
94 | + } | |
95 | + if (0 != strcmp( | |
96 | + buf + i * LINE_SIZE, | |
97 | + buf + (line + i) * LINE_SIZE)) { | |
98 | + b = FALSE; | |
99 | + break; | |
100 | + } | |
101 | + } | |
102 | + | |
103 | + if (b) { | |
104 | + if (i == line) { | |
105 | + /* 完全一致 */ | |
106 | + for (i = line; i < line * 2 - 1; i++) { | |
107 | + *(buf + i * LINE_SIZE) = '\0'; | |
108 | + } | |
109 | + } | |
110 | + continue; | |
111 | + } | |
112 | + | |
113 | + /* 以下は不一致の場合の処理 */ | |
114 | + for (i = 0; i < line * 2 - 1; i++) { | |
115 | + strcpy(buf + i * LINE_SIZE, | |
116 | + buf + (i + 1) * LINE_SIZE); | |
117 | + } | |
118 | + fwrite(buf + (line - 1) * LINE_SIZE, | |
119 | + strlen(buf + (line - 1) * LINE_SIZE), 1, out); | |
120 | + } | |
121 | + | |
122 | + /* 残っているデータを出力 */ | |
123 | + for (i = line; i < line * 2 - 1; i++) { | |
124 | + if ('\0' == *(buf + i * LINE_SIZE)) { | |
125 | + break; | |
126 | + } | |
127 | + fwrite(buf + i * LINE_SIZE, strlen(buf + i * LINE_SIZE), 1, out); | |
128 | + } | |
129 | +} | |
130 | + | |
131 | +int | |
132 | +main(int argc, char *argv[]) | |
133 | +{ | |
134 | + int dupline = 1; | |
135 | + char *buf; | |
136 | + int c; | |
137 | + int option_index; | |
138 | + static struct option options[] = { | |
139 | + {"dedupulicate", required_argument, NULL, 'd'}, | |
140 | + {"help", no_argument, NULL, 'h'}, | |
141 | + {"version", no_argument, NULL, 'v'}, | |
142 | + {NULL, 0, NULL, 0} | |
143 | + }; | |
144 | + | |
145 | + while (-1 != (c = getopt_long(argc, argv, "d:hv", | |
146 | + options, &option_index))) { | |
147 | + switch (c) { | |
148 | + case 'd': | |
149 | + if (0 == (dupline = strtol(optarg, NULL, 10))) { | |
150 | + dupline = 1; | |
151 | + } | |
152 | + break; | |
153 | + case 'h': | |
154 | + showHelp(); | |
155 | + return 0; | |
156 | + case 'v': | |
157 | + showVersion(); | |
158 | + return 0; | |
159 | + default: | |
160 | + fprintf(stderr, "想定外のgetoptからの戻り: %c\n", c); | |
161 | + return 1; | |
162 | + } | |
163 | + } | |
164 | + | |
165 | + /* バッファ領域の確保 */ | |
166 | + if (NULL == (buf = malloc((size_t) (LINE_SIZE * dupline * 2)))) { | |
167 | + int err = errno; | |
168 | + fprintf(stderr, "%s %s(%d) %s\n", | |
169 | + __FUNCTION__, __FILE__, __LINE__, strerror(err)); | |
170 | + return 1; | |
171 | + } | |
172 | + | |
173 | + setmode(0, O_BINARY); | |
174 | + setmode(1, O_BINARY); | |
175 | + | |
176 | + deduplicate(stdin, stdout, buf, dupline); | |
177 | + | |
178 | + free(buf); | |
179 | + return 0; | |
180 | +} | |
181 | + |
@@ -0,0 +1,25 @@ | ||
1 | +# $Id: makefile,v 1.1 2011/03/01 11:00:07 tfuruka1 Exp $ | |
2 | +# | |
3 | +# uniqコマンドで対応できなかったので dedup を作る。 | |
4 | +# | |
5 | +# | |
6 | +CC = x86_64-w64-mingw32-gcc | |
7 | +CC = i686-w64-mingw32-gcc | |
8 | +CFLAGS= -g -Wall -W -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings \ | |
9 | + -Wconversion -Wfloat-equal -Wpointer-arith \ | |
10 | + --exec-charset=cp932 --input-charset=utf-8 | |
11 | + | |
12 | +EXE=dedup | |
13 | +OBJS=main.o | |
14 | + | |
15 | +../../bin/$(EXE) : $(EXE) | |
16 | + -cp $(EXE) $@ | |
17 | + | |
18 | +$(EXE) : $(OBJS) | |
19 | + $(CC) $(CFLAGS) -o $@ $(OBJS) | |
20 | + | |
21 | +clean : | |
22 | + -rm -f *.o *~ | |
23 | + | |
24 | +clean-all : clean | |
25 | + -rm -f *.exe |