SDDSlib
Loading...
Searching...
No Matches
sddsselect.c File Reference

Creates an SDDS data set from another data set based on matching data in a third data set. More...

#include "mdb.h"
#include "SDDS.h"
#include "scan.h"

Go to the source code of this file.

Enumerations

enum  option_type {
  SET_MATCH_COLUMN , SET_EQUATE_COLUMN , SET_NOWARNINGS , SET_INVERT ,
  SET_REUSE , SET_PIPE , SET_MAJOR_ORDER , N_OPTIONS
}
 

Functions

int main (int argc, char **argv)
 

Variables

char * option [N_OPTIONS]
 
char * USAGE
 

Detailed Description

Creates an SDDS data set from another data set based on matching data in a third data set.

This program selects rows from <input1> that have (or do not have, if inverted) a matching entry in <input2>, based on specified matching or equating columns. The output is written to <output>, or <input1> is replaced if <output> is not provided.

Usage

sddsselect [OPTIONS] [<input1>] <input2> [<output>]

Options

  • -pipe[=input][,output] Use pipe for input and/or output.
  • -match=<column1>[=<column2>] Specify columns to match between input1 and input2.
  • -equate=<column1>[=<column2>] Specify columns to equate between input1 and input2.
  • -invert Invert the selection to keep non-matching rows.
  • -reuse[=rows][,page] Allow reusing rows or specify page reuse.
  • -majorOrder=row|column Set the output file to row or column major order.
  • -nowarnings Suppress warning messages.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, C. Saunders, R. Soliday, H. Shang

Definition in file sddsselect.c.

Enumeration Type Documentation

◆ option_type

enum option_type

Definition at line 52 of file sddsselect.c.

52 {
53 SET_MATCH_COLUMN,
54 SET_EQUATE_COLUMN,
55 SET_NOWARNINGS,
56 SET_INVERT,
57 SET_REUSE,
58 SET_PIPE,
59 SET_MAJOR_ORDER,
60 N_OPTIONS
61};

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 89 of file sddsselect.c.

89 {
90 SDDS_DATASET SDDS_1, SDDS_2, SDDS_output;
91 long i, j, i_arg, reuse, reusePage;
92 int64_t rows1, rows2, i1, i2;
93 SCANNED_ARG *s_arg;
94 char s[200], *ptr;
95 char **match_column, **equate_column;
96 long match_columns, equate_columns;
97 char *input1, *input2, *output;
98 long tmpfile_used, retval1, retval2;
99 long warnings, invert;
100 unsigned long pipeFlags, majorOrderFlag;
101 KEYED_EQUIVALENT **keyGroup = NULL;
102 long keyGroups = 0;
103 short columnMajorOrder = -1;
104
106 argc = scanargs(&s_arg, argc, argv);
107 if (argc < 3)
108 bomb(NULL, USAGE);
109
110 input1 = input2 = output = NULL;
111 match_column = equate_column = NULL;
112 match_columns = equate_columns = reuse = reusePage = 0;
113 tmpfile_used = invert = 0;
114 warnings = 1;
115 pipeFlags = 0;
116
117 for (i_arg = 1; i_arg < argc; i_arg++) {
118 if (s_arg[i_arg].arg_type == OPTION) {
119 delete_chars(s_arg[i_arg].list[0], "_");
120 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
121 case SET_MAJOR_ORDER:
122 majorOrderFlag = 0;
123 s_arg[i_arg].n_items--;
124 if (s_arg[i_arg].n_items > 0 &&
125 (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
126 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
127 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
128 SDDS_Bomb("invalid -majorOrder syntax/values");
129 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
130 columnMajorOrder = 1;
131 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
132 columnMajorOrder = 0;
133 break;
134 case SET_MATCH_COLUMN:
135 if (s_arg[i_arg].n_items != 2)
136 SDDS_Bomb("invalid -match syntax");
137 if (match_columns != 0)
138 SDDS_Bomb("only one -match option may be given");
139 match_column = tmalloc(sizeof(*match_column) * 2);
140 if ((ptr = strchr(s_arg[i_arg].list[1], '=')))
141 *ptr++ = 0;
142 else
143 ptr = s_arg[i_arg].list[1];
144 match_column[0] = s_arg[i_arg].list[1];
145 match_column[1] = ptr;
146 match_columns = 1;
147 break;
148 case SET_EQUATE_COLUMN:
149 if (s_arg[i_arg].n_items != 2)
150 SDDS_Bomb("invalid -equate syntax");
151 if (equate_columns != 0)
152 SDDS_Bomb("only one -equate option may be given");
153 equate_column = tmalloc(sizeof(*equate_column) * 2);
154 if ((ptr = strchr(s_arg[i_arg].list[1], '=')))
155 *ptr++ = 0;
156 else
157 ptr = s_arg[i_arg].list[1];
158 equate_column[0] = s_arg[i_arg].list[1];
159 equate_column[1] = ptr;
160 equate_columns = 1;
161 break;
162 case SET_REUSE:
163 if (s_arg[i_arg].n_items == 1)
164 reuse = 1;
165 else {
166 char *reuseOptions[2] = {"rows", "page"};
167 for (i = 1; i < s_arg[i_arg].n_items; i++) {
168 switch (match_string(s_arg[i_arg].list[i], reuseOptions, 2, 0)) {
169 case 0:
170 reuse = 1;
171 break;
172 case 1:
173 reusePage = 1;
174 break;
175 default:
176 SDDS_Bomb("unknown reuse keyword");
177 break;
178 }
179 }
180 }
181 break;
182 case SET_INVERT:
183 invert = 1;
184 break;
185 case SET_NOWARNINGS:
186 warnings = 0;
187 break;
188 case SET_PIPE:
189 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
190 SDDS_Bomb("invalid -pipe syntax");
191 break;
192 default:
193 fprintf(stderr, "error: unknown switch: %s\n", s_arg[i_arg].list[0]);
194 SDDS_Bomb(NULL);
195 break;
196 }
197 } else {
198 if (input1 == NULL)
199 input1 = s_arg[i_arg].list[0];
200 else if (input2 == NULL)
201 input2 = s_arg[i_arg].list[0];
202 else if (output == NULL)
203 output = s_arg[i_arg].list[0];
204 else
205 SDDS_Bomb("too many filenames");
206 }
207 }
208
209 if (pipeFlags & USE_STDIN && input1) {
210 if (output)
211 SDDS_Bomb("too many filenames (sddsxref)");
212 output = input2;
213 input2 = input1;
214 input1 = NULL;
215 }
216 processFilenames("sddsselect", &input1, &output, pipeFlags, !warnings, &tmpfile_used);
217 if (!input2)
218 SDDS_Bomb("second input file not specified (sddsxref)");
219
220 if (equate_columns && match_columns)
221 SDDS_Bomb("only one of -equate or -match may be given");
222 if (!equate_columns && !match_columns)
223 SDDS_Bomb("one of -equate or -match must be given");
224
225 if (!SDDS_InitializeInput(&SDDS_1, input1)) {
226 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
227 exit(EXIT_FAILURE);
228 }
229 if (!SDDS_InitializeInput(&SDDS_2, input2)) {
230 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
231 exit(EXIT_FAILURE);
232 }
233
234 if (match_columns) {
235 if ((j = SDDS_GetColumnIndex(&SDDS_1, match_column[0])) < 0 ||
236 SDDS_GetColumnType(&SDDS_1, j) != SDDS_STRING) {
237 sprintf(s, "error: column %s not found or not string type in file %s", match_column[0], input1 ? input1 : "stdin");
238 SDDS_SetError(s);
239 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
240 }
241 if ((j = SDDS_GetColumnIndex(&SDDS_2, match_column[1])) < 0 ||
242 SDDS_GetColumnType(&SDDS_2, j) != SDDS_STRING) {
243 sprintf(s, "error: column %s not found or not string type in file %s", match_column[1], input2);
244 SDDS_SetError(s);
245 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
246 }
247 }
248 if (equate_columns) {
249 if ((j = SDDS_GetColumnIndex(&SDDS_1, equate_column[0])) < 0 ||
251 sprintf(s, "error: column %s not found or not numeric type in file %s", equate_column[0], input1 ? input1 : "stdin");
252 SDDS_SetError(s);
253 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
254 }
255 if ((j = SDDS_GetColumnIndex(&SDDS_2, equate_column[1])) < 0 ||
257 sprintf(s, "error: column %s not found or not numeric type in file %s", equate_column[1], input2);
258 SDDS_SetError(s);
259 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
260 }
261 }
262
263 if (output && pipeFlags & USE_STDOUT)
264 SDDS_Bomb("too many filenames with -pipe option");
265 if (!output && !(pipeFlags & USE_STDOUT)) {
266 if (warnings)
267 fprintf(stderr, "warning: existing file %s will be replaced (sddsselect)\n", input1 ? input1 : "stdin");
268 tmpfile_used = 1;
269 cp_str(&output, tmpname(NULL));
270 }
271 if (!SDDS_InitializeCopy(&SDDS_output, &SDDS_1, output, "w")) {
272 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
273 exit(EXIT_FAILURE);
274 }
275 if (columnMajorOrder != -1)
276 SDDS_output.layout.data_mode.column_major = columnMajorOrder;
277 else
278 SDDS_output.layout.data_mode.column_major = SDDS_1.layout.data_mode.column_major;
279 if (!SDDS_WriteLayout(&SDDS_output))
280 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
281
282 while ((retval1 = SDDS_ReadPage(&SDDS_1)) > 0) {
283 if (!reusePage) {
284 if ((retval2 = SDDS_ReadPage(&SDDS_2)) <= 0) {
285 if (warnings)
286 fprintf(stderr, "warning: <input2> ends before <input1>\n");
287 if (invert) {
288 /* nothing to match, so everything would normally be thrown out */
289 if (!SDDS_CopyPage(&SDDS_output, &SDDS_1) ||
290 !SDDS_WritePage(&SDDS_output))
291 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
292 continue;
293 } else
294 /* nothing to match, so everything thrown out */
295 break;
296 }
297 } else {
298 if (retval1 == 1 && (retval2 = SDDS_ReadPage(&SDDS_2)) <= 0)
299 SDDS_Bomb("<input2> has no data");
300 SDDS_SetRowFlags(&SDDS_2, 1);
301 }
302 rows1 = SDDS_CountRowsOfInterest(&SDDS_1);
303 rows2 = SDDS_CountRowsOfInterest(&SDDS_2);
304
305 if (!SDDS_StartPage(&SDDS_output, rows1)) {
306 SDDS_SetError("Problem starting output page");
307 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
308 }
309 if (!SDDS_CopyParameters(&SDDS_output, &SDDS_2) ||
310 !SDDS_CopyArrays(&SDDS_output, &SDDS_2)) {
311 SDDS_SetError("Problem copying parameter or array data from second input file");
312 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
313 }
314 if (!SDDS_CopyParameters(&SDDS_output, &SDDS_1) ||
315 !SDDS_CopyArrays(&SDDS_output, &SDDS_1)) {
316 SDDS_SetError("Problem copying parameter or array data from first input file");
317 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
318 }
319 if (rows1) {
320 if (match_columns) {
321 char **string1, **string2;
322 long matched;
323 string2 = NULL;
324 if (!(string1 = SDDS_GetColumn(&SDDS_1, match_column[0]))) {
325 fprintf(stderr, "Error: problem getting column %s from file %s\n", match_column[0], input1 ? input1 : "stdin");
326 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
327 }
328 if (rows2 && !(string2 = SDDS_GetColumn(&SDDS_2, match_column[1]))) {
329 fprintf(stderr, "Error: problem getting column %s from file %s\n", match_column[1], input2);
330 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
331 }
332 if (rows2)
333 keyGroup = MakeSortedKeyGroups(&keyGroups, SDDS_STRING, string2, rows2);
334 for (i1 = 0; i1 < rows1; i1++) {
335 if (!SDDS_CopyRowDirect(&SDDS_output, i1, &SDDS_1, i1)) {
336 sprintf(s, "Problem copying row %" PRId64 " of first data set", i1);
337 SDDS_SetError(s);
338 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
339 }
340 matched = 0;
341 if (rows2 && (i2 = FindMatchingKeyGroup(keyGroup, keyGroups, SDDS_STRING, string1 + i1, reuse)) >= 0) {
342 matched = 1;
343 }
344 if ((!matched && !invert) || (matched && invert)) {
345 if (!SDDS_AssertRowFlags(&SDDS_output, SDDS_INDEX_LIMITS, i1, i1, 0))
346 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
347 }
348 }
349 if (string1) {
350 for (i = 0; i < rows1; i++)
351 free(string1[i]);
352 free(string1);
353 string1 = NULL;
354 }
355 if (string2) {
356 for (i = 0; i < rows2; i++)
357 free(string2[i]);
358 free(string2);
359 string2 = NULL;
360 }
361 for (i = 0; i < keyGroups; i++) {
362 if (keyGroup[i]) {
363 if (keyGroup[i]->equivalent)
364 free(keyGroup[i]->equivalent);
365 free(keyGroup[i]);
366 keyGroup[i] = NULL;
367 }
368 }
369 if (keyGroups) {
370 free(keyGroup);
371 keyGroup = NULL;
372 keyGroups = 0;
373 }
374 } else if (equate_columns) {
375 double *value1, *value2;
376 long equated;
377 value2 = NULL;
378 if (!(value1 = SDDS_GetColumnInDoubles(&SDDS_1, equate_column[0]))) {
379 fprintf(stderr, "Error: problem getting column %s from file %s\n", equate_column[0], input1 ? input1 : "stdin");
380 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
381 }
382 if (rows2 && !(value2 = SDDS_GetColumnInDoubles(&SDDS_2, equate_column[1]))) {
383 fprintf(stderr, "Error: problem getting column %s from file %s\n", equate_column[1], input2);
384 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
385 }
386 if (rows2)
387 keyGroup = MakeSortedKeyGroups(&keyGroups, SDDS_DOUBLE, value2, rows2);
388 for (i1 = 0; i1 < rows1; i1++) {
389 if (!SDDS_CopyRowDirect(&SDDS_output, i1, &SDDS_1, i1)) {
390 sprintf(s, "Problem copying row %" PRId64 " of first data set", i1);
391 SDDS_SetError(s);
392 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
393 }
394 equated = 0;
395 if (rows2 &&
396 (i2 = FindMatchingKeyGroup(keyGroup, keyGroups, SDDS_DOUBLE, value1 + i1, reuse)) >= 0) {
397 equated = 1;
398 }
399 if ((!equated && !invert) || (equated && invert)) {
400 if (!SDDS_AssertRowFlags(&SDDS_output, SDDS_INDEX_LIMITS, i1, i1, 0))
401 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
402 }
403 }
404 if (value1)
405 free(value1);
406 value1 = NULL;
407 if (rows2 && value2)
408 free(value2);
409 value2 = NULL;
410 for (i = 0; i < keyGroups; i++) {
411 if (keyGroup[i]) {
412 if (keyGroup[i]->equivalent)
413 free(keyGroup[i]->equivalent);
414 free(keyGroup[i]);
415 keyGroup[i] = NULL;
416 }
417 }
418 if (keyGroups) {
419 free(keyGroup);
420 keyGroup = NULL;
421 keyGroups = 0;
422 }
423 }
424 }
425 if (!SDDS_WritePage(&SDDS_output)) {
426 SDDS_SetError("Problem writing data to output file");
427 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
428 }
429 }
430
431 if (!SDDS_Terminate(&SDDS_1) || !SDDS_Terminate(&SDDS_2) || !SDDS_Terminate(&SDDS_output)) {
432 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
433 exit(EXIT_FAILURE);
434 }
435 if (tmpfile_used && !replaceFileAndBackUp(input1, output))
436 exit(EXIT_FAILURE);
437 free_scanargs(&s_arg, argc);
438 if (match_columns)
439 free(match_column);
440 return EXIT_SUCCESS;
441}
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyRowDirect(SDDS_DATASET *SDDS_target, int64_t target_row, SDDS_DATASET *SDDS_source, int64_t source_row)
Definition SDDS_copy.c:834
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
int32_t SDDS_CopyArrays(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:334
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_AssertRowFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode,...)
Sets acceptance flags for rows based on specified criteria.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
int32_t SDDS_SetRowFlags(SDDS_DATASET *SDDS_dataset, int32_t row_flag_value)
Sets the acceptance flags for all rows in the current data table of a data set.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
Definition replacefile.c:75
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
KEYED_EQUIVALENT ** MakeSortedKeyGroups(long *keyGroups, long keyType, void *data, long points)
Create sorted key groups from data.
long FindMatchingKeyGroup(KEYED_EQUIVALENT **keyGroup, long keyGroups, long keyType, void *searchKeyData, long reuse)
Find a matching key group for a search key.
char * tmpname(char *s)
Supplies a unique temporary filename.
Definition tmpname.c:34

Variable Documentation

◆ option

char* option[N_OPTIONS]
Initial value:
= {
"match",
"equate",
"nowarnings",
"invert",
"reuse",
"pipe",
"majorOrder",
}

Definition at line 63 of file sddsselect.c.

63 {
64 "match",
65 "equate",
66 "nowarnings",
67 "invert",
68 "reuse",
69 "pipe",
70 "majorOrder",
71};

◆ USAGE

char* USAGE
Initial value:
= "Usage: sddsselect [OPTIONS] [<input1>] <input2> [<output>]\n\
\n\
Options:\n\
-pipe[=input][,output] Use pipe for input and/or output.\n\
-match=<column1>[=<column2>] Specify columns to match between input1 and input2.\n\
-equate=<column1>[=<column2>] Specify columns to equate between input1 and input2.\n\
-invert Invert the selection to keep non-matching rows.\n\
-reuse[=rows][,page] Allow reusing rows or specify page reuse.\n\
-majorOrder=row|column Set the output file to row or column major order.\n\
-nowarnings Suppress warning messages.\n\
\n\
Example:\n\
sddsselect -match=colA=colB input1.sdds input2.sdds output.sdds\n\
\n\
Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n"

Definition at line 73 of file sddsselect.c.