read: add -r to read runes instead of bytes (thanks umbraticus)

This commit is contained in:
Sigrid Solveig Haflínudóttir 2022-11-05 23:41:43 +00:00
parent 1b02c81c18
commit 744475a503
2 changed files with 58 additions and 22 deletions

View file

@ -10,12 +10,15 @@ cat, read \- catenate files
.B read
[
.B -m
] [
|
.B -n
.I nlines
] [
|
.B -c
.I nbytes
|
.B -r
.I nrunes
] [
.I file ...
]
@ -59,20 +62,14 @@ flag causes it to continue reading and writing multiple lines until end of file;
causes it to read no more than
.I nlines
lines.
.PP
With the
The
.B -c
flag,
.I read
copies exactly
.I nbytes
of characters instead of lines. It is mutually exclusive with
.B -n
and
.B -m
flag.
.B -r
flags specify a number of bytes or runes to read instead of lines.
.PP
.I Read
When reading lines,
.I read
always executes a single
.B write
for each line of input, which can be helpful when

View file

@ -2,8 +2,7 @@
#include <libc.h>
int multi;
int nlines;
vlong nchars;
vlong count;
char *status = nil;
int
@ -50,7 +49,7 @@ lines(int fd, char *file)
do{
if(line(fd, file) == 0)
break;
}while(multi || --nlines>0);
}while(multi || --count > 0);
}
void
@ -60,10 +59,10 @@ chars(int fd, char *file)
vlong m;
int n;
for(m = 0; m < nchars; m += n){
for(m = 0; m < count; m += n){
n = sizeof(buf);
if(n > (nchars - m))
n = nchars - m;
if(n > (count - m))
n = count - m;
if((n = read(fd, buf, n)) < 0){
fprint(2, "read: error reading %s: %r\n", file);
exits("read error");
@ -77,10 +76,46 @@ chars(int fd, char *file)
}
}
void
runes(int fd, char *file)
{
char buf[8*1024], *s, *e;
Rune r;
while(count > 0){
e = buf + read(fd, buf, count + UTFmax < sizeof buf ? count : sizeof buf - UTFmax);
if(e < buf){
fprint(2, "read: error reading %s: %r\n", file);
exits("read error");
}
if(e == buf)
break;
for(s = buf; s < e && fullrune(s, e - s); s += chartorune(&r, s))
count--;
if(s < e){
while(!fullrune(s, e - s))
switch(read(fd, e, 1)){
case -1:
fprint(2, "read: error reading %s: %r\n", file);
exits("read error");
case 0:
fprint(2, "warning: partial rune at end of %s: %r\n", file);
write(1, buf, e - buf);
return;
case 1:
e++;
break;
}
count--;
}
write(1, buf, e - buf);
}
}
void
usage(void)
{
fprint(2, "usage: read [-m] [-n nlines] [-c nbytes] [files...]\n");
fprint(2, "usage: read [ -m | -n nlines | -c nbytes | -r nrunes ] [ file ... ]\n");
exits("usage");
}
@ -93,11 +128,15 @@ main(int argc, char *argv[])
proc = lines;
ARGBEGIN{
case 'c':
nchars = atoll(EARGF(usage()));
count = atoll(EARGF(usage()));
proc = chars;
break;
case 'r':
count = atoll(EARGF(usage()));
proc = runes;
break;
case 'n':
nlines = atoi(EARGF(usage()));
count = atoi(EARGF(usage()));
break;
case 'm':
multi = 1;