Rename line to lines
* It can now extract multiple lines, I'm not super excited about the code, but it works at least * Add ADVANCE_PTR macro to util
This commit is contained in:
parent
5be53acc72
commit
a124089295
17
doc/line.1
17
doc/line.1
|
@ -1,17 +0,0 @@
|
||||||
.TH LINE 1
|
|
||||||
.SH NAME
|
|
||||||
line \- extract line from input
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B line
|
|
||||||
.IR ln
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.B line
|
|
||||||
extracts the ln'th line from input provided over STDIN
|
|
||||||
.SH EXAMPLES
|
|
||||||
Get the 3rd line from the file line.1
|
|
||||||
.PP
|
|
||||||
.nf
|
|
||||||
.RS
|
|
||||||
line 3 < line.1
|
|
||||||
.RE
|
|
||||||
.fi
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
.TH LINES 1
|
||||||
|
.SH NAME
|
||||||
|
line \- extract lines from input
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B line
|
||||||
|
.IR [LINES...]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B line
|
||||||
|
extracts lines from stdin. If multiple lines are provided, they will be sorted
|
||||||
|
numerically. If the same line is specified twice, it will only be extracted
|
||||||
|
once.
|
||||||
|
.SH EXAMPLES
|
||||||
|
Get the 3rd line from the file line.1
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
.RS
|
||||||
|
line 3 < line.1
|
||||||
|
.RE
|
||||||
|
.fi
|
||||||
|
Get the 3rd, 4th and 5th lines from the file line.1
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
.RS
|
||||||
|
line 3 5 4 < line.1
|
||||||
|
.RE
|
||||||
|
.fi
|
|
@ -26,40 +26,73 @@ const char *argv0;
|
||||||
void
|
void
|
||||||
usage()
|
usage()
|
||||||
{
|
{
|
||||||
die("usage: %s ln", argv0);
|
die("usage: %s [LINE...]", argv0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getlineno(const char *s)
|
||||||
|
{
|
||||||
|
int ln;
|
||||||
|
char *p;
|
||||||
|
ln = (int)strtol(s, &p, 10);
|
||||||
|
if (errno != 0 || *p != '\0' || ln <= 0) {
|
||||||
|
errno ? edie("strtol: ") : die("unable to parse line");
|
||||||
|
}
|
||||||
|
return ln;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert ln into lns, assuming it is lns_size long and 0 initialised */
|
||||||
|
int *
|
||||||
|
insertln(int ln, int *lns, size_t lns_size)
|
||||||
|
{
|
||||||
|
int *ip = lns;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
while (lns_size && *ip && *ip < ln) {
|
||||||
|
ADVANCE_PTR(ip, lns_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (lns_size) {
|
||||||
|
j = *ip;
|
||||||
|
*ip = ln;
|
||||||
|
ln = j;
|
||||||
|
ADVANCE_PTR(ip, lns_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lns;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the ln'th line from fp to stdout */
|
|
||||||
void
|
void
|
||||||
line(FILE *fp, int ln)
|
printlines(FILE *fp, int *lns, size_t lns_size)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int cln = 1;
|
int cln = 1;
|
||||||
while ((c = fgetc(fp)) != '\0') {
|
while (lns_size && (c = fgetc(fp)) != '\0') {
|
||||||
if (cln > ln) break;
|
if (cln > *lns) { ADVANCE_PTR(lns, lns_size); }
|
||||||
if (cln == ln) putc(c, stdout);
|
if (cln == *lns) putc(c, stdout);
|
||||||
if (c == '\n') cln++;
|
if (c == '\n') cln++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print a specified line from stdin */
|
/* Print specified lines from stdin */
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
int *lns;
|
||||||
SET_ARGV0();
|
SET_ARGV0();
|
||||||
|
|
||||||
if (argc < 1) usage();
|
if (argc < 1) usage();
|
||||||
int ln;
|
size_t lns_size = argc;
|
||||||
char *p;
|
lns = ecalloc(lns_size, sizeof(int));
|
||||||
ln = (int)strtol(argv[0], &p, 10);
|
|
||||||
if (errno != 0 || *p != '\0') {
|
while (argc) {
|
||||||
errno ? edie("strtol: ") : die("unable to parse ln");
|
lns = insertln(getlineno(argv[0]), lns, lns_size);
|
||||||
}
|
|
||||||
SHIFT_ARGS();
|
SHIFT_ARGS();
|
||||||
|
}
|
||||||
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
fp = fdopen(STDIN_FILENO, "r");
|
fp = fdopen(STDIN_FILENO, "r");
|
||||||
line(fp, ln);
|
printlines(fp, lns, lns_size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* SEE COPYRIGHT NOTICE IN util.c */
|
/* SEE COPYRIGHT NOTICE IN util.c */
|
||||||
|
|
||||||
#define SHIFT_ARGS() argv++; argc--;
|
#define ADVANCE_PTR(ptr, size) (ptr)++; (size)--
|
||||||
|
#define SHIFT_ARGS() ADVANCE_PTR(argv, argc)
|
||||||
#define SET_ARGV0() argv0 = argv[0]; SHIFT_ARGS();
|
#define SET_ARGV0() argv0 = argv[0]; SHIFT_ARGS();
|
||||||
|
|
||||||
void die(const char *fmt, ...);
|
void die(const char *fmt, ...);
|
||||||
|
|
Loading…
Reference in New Issue