Skip to content

Instantly share code, notes, and snippets.

@tsupo
Created May 14, 2009 09:43
Show Gist options
  • Select an option

  • Save tsupo/111589 to your computer and use it in GitHub Desktop.

Select an option

Save tsupo/111589 to your computer and use it in GitHub Desktop.
cut
/*
* cut.c
*
* cut --- 行の中から指定フィールドを切り出す
*
* 形式
* (1) cut -c<フィールド> [filename ...]
* (2) cut -f<フィールド> [-d<セパレータ>] [-s]
* 機能
* (1) 空白文字(スペース)をフィールドの区切りとみなし、
* 指定フィールドを切り出す
* (2) 指定されたセパレータをフィールドの区切りとみな
* し、指定フィールドを切り出す。-dオプションでセ
* パレータが指定されない場合は、スペースおよびタ
* ブをセパレータとみなす。-sオプションが指定され
* る場合は、セパレータの含まれない行はそのまま出
* 力するが、指定されない場合は、セパレータの含ま
* れない行は捨てられる。なお、セパレータは文字列
* でも構わない(UNIX標準の cut (1) はセパレータは
* 単一の文字でなければならない)
* フィールドの指定の仕方
* 数 "数"番目のフィールド
* 数- "数"番目のフィールドから行の終わりまで
* 数1-数2 "数1"番目のフィールドから"数2"番目のフィールドまで
* -数 行の始めから"数"番目のフィールドまで
* 数1,数2 "数1"番目のフィールドと"数2"番目のフィールド
* を、それぞれ切り出す。切り出したいフィールドがいくつもある場
* 合は、例えば
* 数1-数2,数3,数4-数5,数6,数7,数8-
* ("数1"番目から"数2"番目までと"数3"番目、 "数4"番目から
* "数5"番目まで、さらに"数6"番目と"数7"番目、および"数8"
* 番目から行の終わりまで を切り出す)
* のように、フィールド指定を組合わせることもできる
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXFIELD (BUFSIZ-1)
#ifndef NUL
#define NUL '\0'
#endif
char separator[BUFSIZ];
char valid[MAXFIELD+1];
/* mode
* 7 6 5 4 3 2 1 0
* +-+-+-+-+-+-+-+-+
* | | | | | | | | |
* +-+-+-+-+-+-+-+-+
* | | | |
* | | | +---- specified -s option (1) or not (0)
* | | +------ specified -f (1) or not (0)
* | +-------- specified -c (1) or not (0)
* +---------- specified -d<delimiter> (1) or not (0)
*/
#define SMODE 0x01
#define FMODE 0x02
#define CMODE 0x04
#define DMODE 0x08
#define TRUE (1)
#define FALSE (!TRUE)
/* void setField(); */
void ccut(), ffcut(), fdcut();
#if 0
void
cut( FILE *fp, unsigned char mode )
{
( mode & CMODE ) ? ccut( fp, mode ) : fcut( fp, mode );
}
void
fcut( FILE *fp, unsigned char mode )
{
( mode & DMODE ) ? fdcut( fp, mode ) : ffcut( fp, mode );
}
#else
#define cut(fp,mode) (((mode)&CMODE)?ccut((fp),(mode)):fcut((fp),(mode)))
#define fcut(fp,mode) (((mode)&DMODE)?fdcut((fp),(mode)):ffcut((fp),(mode)))
#endif
void
setField( char *p )
{
char *q;
if ( p && (((*p >='0') && (*p <= '9')) || (*p == ',') || (*p == '-')) ) {
if ( (q = strchr( p, ',' )) != NULL ) {
char buf[BUFSIZ];
if ( *p == ',' ) {
p++;
}
while ( (q = strchr( p, ',' )) != NULL ) {
if ( *p == ',' ) {
p++;
continue;
}
strncpy( buf, p, q - p );
buf[q - p] = NUL;
setField( buf );
p = q + 1;
}
if ( p ) {
setField( p );
}
}
else if ( (q = strchr( p, '-' )) != NULL ) {
int start = 0;
int end = MAXFIELD - 1;
int i;
if ( *p == '-' ) {
if ( *(p + 1) && (*(p + 1) >= '0') && (*(p + 1) <= '9') ) {
end = atol( p + 1 );
}
}
else if ( (*p >= '0') && (*p <= '9') ) {
start = atol( p );
p = q + 1;
if ( p && (*p >= '0') && (*p <= '9') ) {
end = atol( p );
}
}
if ( (0 <= start) && (start <= end) && (end < MAXFIELD) ) {
for ( i = start; i <= end; i++ ) {
valid[i] = TRUE;
}
}
}
else {
int field = atoi( p );
if ( (field >= 0) && (field < MAXFIELD) ) {
valid[field] = TRUE;
}
}
}
}
void
main( argc, argv )
int argc;
char *argv[];
{
unsigned char mode = 0x00;
int i, fcnt = 0;
FILE *fp;
for ( i = 1; i < argc; i++ ) {
if ( argv[i][0] == '-' ) {
switch ( argv[i][1] ) {
case 's':
mode = !((mode & SMODE) == SMODE) ? (mode | SMODE)
: (mode & ~SMODE);
break;
case 'c':
mode |= CMODE;
setField( &argv[i][2] );
break;
case 'f':
mode |= FMODE;
setField( &argv[i][2] );
break;
case 'd':
mode |= DMODE;
strcpy( separator, &argv[i][2] );
break;
case '-':
break;
default:
fprintf( stderr, "cut: illegal option: <%s>.\n", argv[i] );
exit( 2 );
/* not reached */
break;
}
if ( argv[i][1] == '-' )
strcpy( argv[i], &argv[i][1] );
else
continue;
}
if ( !( mode & (CMODE | FMODE) ) ) {
fputs( "cut: too few argument.\n", stderr );
exit( 2 );
}
if ( ( fp = fopen( argv[i], "r" ) ) == NULL ) {
fprintf( stderr, "cut: cannot open <%s>.\n", argv[i] );
exit( 1 );
}
cut( fp, mode );
fclose( fp );
fcnt++;
}
if ( fcnt == 0 ) {
if ( !( mode & (CMODE | FMODE) ) ) {
fputs( "cut: too few argument.\n", stderr );
exit( 2 );
}
cut( stdin, mode );
}
exit( 0 );
}
void
ccut( fp, mode )
FILE *fp;
unsigned char mode;
{
char *p, buf[BUFSIZ], out[BUFSIZ];
int cnt, i;
while ( ( p = fgets( buf, BUFSIZ - 1, fp ) ) != NULL ) {
cnt = 0;
i = 0;
out[i] = NUL;
while ( *p ) {
if ( *p == ' ' ) {
if ( valid[cnt] == TRUE )
out[i++] = *p;
cnt++;
while ( *p && ( *p == ' ' ) )
p++;
if ( !(*p) )
break;
}
if ( valid[cnt] == TRUE ) {
out[i++] = *p;
}
p++;
}
if ( (i > 0) && (out[i - 1] != '\n') ) {
out[i++] = '\n';
}
out[i] = NUL;
if ( out[0] != NUL )
fputs( out, stdout );
else if ( mode & SMODE )
fputs( buf, stdout );
}
if ( fp == stdin )
clearerr( stdin );
}
void
ffcut( fp, mode )
FILE *fp;
unsigned char mode;
{
char *p, buf[BUFSIZ], out[BUFSIZ];
int cnt, i;
while ( ( p = fgets( buf, BUFSIZ - 1, fp ) ) != NULL ) {
cnt = 0;
i = 0;
out[i] = NUL;
while ( *p ) {
if ( ( *p == ' ' ) || ( *p == '\t' ) ) {
if ( valid[cnt] == TRUE )
out[i++] = *p;
cnt++;
while ( *p && ( ( *p == ' ' ) && ( *p == '\t' ) ) )
p++;
if ( !(*p) )
break;
}
if ( valid[cnt] == TRUE ) {
out[i++] = *p;
}
p++;
}
if ( (i > 0) && (out[i - 1] != '\n') ) {
out[i++] = '\n';
}
out[i] = NUL;
if ( out[0] != NUL )
fputs( out, stdout );
else if ( mode & SMODE )
fputs( buf, stdout );
}
if ( fp == stdin )
clearerr( stdin );
}
void
fdcut( fp, mode )
FILE *fp;
unsigned char mode;
{
char *p, buf[BUFSIZ], out[BUFSIZ];
int cnt, i;
while ( ( p = fgets( buf, BUFSIZ - 1, fp ) ) != NULL ) {
cnt = 0;
i = 0;
out[i] = NUL;
while ( *p ) {
if ( !strncmp( p, separator, strlen(separator) ) ) {
if ( valid[cnt] == TRUE ) {
if ( ( i == 0 ) || ( out[i-1] != ' ' ) )
out[i++] = ' ';
}
cnt++;
p += strlen(separator);
continue;
}
if ( valid[cnt] == TRUE )
out[i++] = *p;
p++;
}
if ( (i > 0) && (out[i - 1] != '\n') ) {
out[i++] = '\n';
}
out[i] = NUL;
if ( out[0] != NUL )
fputs( out, stdout );
else if ( mode & SMODE )
fputs( buf, stdout );
}
if ( fp == stdin )
clearerr( stdin );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment