mirror of
https://github.com/coreutils/coreutils.git
synced 2024-11-24 18:33:47 +08:00
paste: add the -z,--zero-terminated option
* doc/coreutils.texi (paste invocation): Reference -z description. * src/paste.c (main): Parameterize the use of '\n'. * tests/misc/paste.pl: Add test cases. * NEWS: Mention the new feature.
This commit is contained in:
parent
0e46753d7c
commit
8297568ec6
2
NEWS
2
NEWS
@ -33,7 +33,7 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
** New features
|
||||
|
||||
comm, cut, head, tail now have the -z,--zero-terminated option, and
|
||||
comm, cut, head, paste, tail now have the -z,--zero-terminated option, and
|
||||
tac --separator accepts an empty argument, to work with NUL delimited items.
|
||||
|
||||
dd now summarizes sizes in --human-readable format too, not just --si.
|
||||
|
@ -6004,6 +6004,8 @@ $ paste -d '%_' num2 let3 num2
|
||||
%c_
|
||||
@end example
|
||||
|
||||
@optZeroTerminated
|
||||
|
||||
@end table
|
||||
|
||||
@exitstatus
|
||||
|
26
src/paste.c
26
src/paste.c
@ -67,10 +67,13 @@ static char *delims;
|
||||
/* A pointer to the character after the end of 'delims'. */
|
||||
static char const *delim_end;
|
||||
|
||||
static unsigned char line_delim = '\n';
|
||||
|
||||
static struct option const longopts[] =
|
||||
{
|
||||
{"serial", no_argument, NULL, 's'},
|
||||
{"delimiters", required_argument, NULL, 'd'},
|
||||
{"zero-terminated", no_argument, NULL, 'z'},
|
||||
{GETOPT_HELP_OPTION_DECL},
|
||||
{GETOPT_VERSION_OPTION_DECL},
|
||||
{NULL, 0, NULL, 0}
|
||||
@ -250,7 +253,7 @@ paste_parallel (size_t nfiles, char **fnamptr)
|
||||
while (chr != EOF)
|
||||
{
|
||||
sometodo = true;
|
||||
if (chr == '\n')
|
||||
if (chr == line_delim)
|
||||
break;
|
||||
xputchar (chr);
|
||||
chr = getc (fileptr[i]);
|
||||
@ -295,7 +298,7 @@ paste_parallel (size_t nfiles, char **fnamptr)
|
||||
write_error ();
|
||||
delims_saved = 0;
|
||||
}
|
||||
xputchar ('\n');
|
||||
xputchar (line_delim);
|
||||
}
|
||||
continue; /* Next read of files, or exit. */
|
||||
}
|
||||
@ -316,7 +319,7 @@ paste_parallel (size_t nfiles, char **fnamptr)
|
||||
/* Except for last file, replace last newline with delim. */
|
||||
if (i + 1 != nfiles)
|
||||
{
|
||||
if (chr != '\n' && chr != EOF)
|
||||
if (chr != line_delim && chr != EOF)
|
||||
xputchar (chr);
|
||||
if (*delimptr != EMPTY_DELIM)
|
||||
xputchar (*delimptr);
|
||||
@ -327,7 +330,7 @@ paste_parallel (size_t nfiles, char **fnamptr)
|
||||
{
|
||||
/* If the last line of the last file lacks a newline,
|
||||
print one anyhow. POSIX requires this. */
|
||||
char c = (chr == EOF ? '\n' : chr);
|
||||
char c = (chr == EOF ? line_delim : chr);
|
||||
xputchar (c);
|
||||
}
|
||||
}
|
||||
@ -386,7 +389,7 @@ paste_serial (size_t nfiles, char **fnamptr)
|
||||
while ((charnew = getc (fileptr)) != EOF)
|
||||
{
|
||||
/* Process the old character. */
|
||||
if (charold == '\n')
|
||||
if (charold == line_delim)
|
||||
{
|
||||
if (*delimptr != EMPTY_DELIM)
|
||||
xputchar (*delimptr);
|
||||
@ -405,8 +408,8 @@ paste_serial (size_t nfiles, char **fnamptr)
|
||||
xputchar (charold);
|
||||
}
|
||||
|
||||
if (charold != '\n')
|
||||
xputchar ('\n');
|
||||
if (charold != line_delim)
|
||||
xputchar (line_delim);
|
||||
|
||||
if (ferror (fileptr))
|
||||
{
|
||||
@ -446,6 +449,9 @@ each FILE, separated by TABs, to standard output.\n\
|
||||
fputs (_("\
|
||||
-d, --delimiters=LIST reuse characters from LIST instead of TABs\n\
|
||||
-s, --serial paste one file at a time instead of in parallel\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-z, --zero-terminated line delimiter is NUL, not newline\n\
|
||||
"), stdout);
|
||||
fputs (HELP_OPTION_DESCRIPTION, stdout);
|
||||
fputs (VERSION_OPTION_DESCRIPTION, stdout);
|
||||
@ -473,7 +479,7 @@ main (int argc, char **argv)
|
||||
have_read_stdin = false;
|
||||
serial_merge = false;
|
||||
|
||||
while ((optc = getopt_long (argc, argv, "d:s", longopts, NULL)) != -1)
|
||||
while ((optc = getopt_long (argc, argv, "d:sz", longopts, NULL)) != -1)
|
||||
{
|
||||
switch (optc)
|
||||
{
|
||||
@ -486,6 +492,10 @@ main (int argc, char **argv)
|
||||
serial_merge = true;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
line_delim = '\0';
|
||||
break;
|
||||
|
||||
case_GETOPT_HELP_CHAR;
|
||||
|
||||
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
|
||||
|
@ -34,6 +34,11 @@ my @Tests =
|
||||
['no-nl-3', {IN=>"a"}, {IN=>"b\n"}, {OUT=>"a\tb\n"}],
|
||||
['no-nl-4', {IN=>"a\n"}, {IN=>"b\n"}, {OUT=>"a\tb\n"}],
|
||||
|
||||
['zno-nl-1', '-z', {IN=>"a"}, {IN=>"b"}, {OUT=>"a\tb\0"}],
|
||||
['zno-nl-2', '-z', {IN=>"a\0"}, {IN=>"b"}, {OUT=>"a\tb\0"}],
|
||||
['zno-nl-3', '-z', {IN=>"a"}, {IN=>"b\0"}, {OUT=>"a\tb\0"}],
|
||||
['zno-nl-4', '-z', {IN=>"a\0"}, {IN=>"b\0"}, {OUT=>"a\tb\0"}],
|
||||
|
||||
# Same as above, but with a two lines in each input file and
|
||||
# the addition of the -d option to make SPACE be the output delimiter.
|
||||
['no-nla1', '-d" "', {IN=>"1\na"}, {IN=>"2\nb"}, {OUT=>"1 2\na b\n"}],
|
||||
@ -41,6 +46,11 @@ my @Tests =
|
||||
['no-nla3', '-d" "', {IN=>"1\na"}, {IN=>"2\nb\n"}, {OUT=>"1 2\na b\n"}],
|
||||
['no-nla4', '-d" "', {IN=>"1\na\n"}, {IN=>"2\nb\n"}, {OUT=>"1 2\na b\n"}],
|
||||
|
||||
['zno-nla1', '-zd" "', {IN=>"1\0a"}, {IN=>"2\0b"}, {OUT=>"1 2\0a b\0"}],
|
||||
['zno-nla2', '-zd" "', {IN=>"1\0a\0"}, {IN=>"2\0b"}, {OUT=>"1 2\0a b\0"}],
|
||||
['zno-nla3', '-zd" "', {IN=>"1\0a"}, {IN=>"2\0b\0"}, {OUT=>"1 2\0a b\0"}],
|
||||
['zno-nla4', '-zd" "', {IN=>"1\0a\0"}, {IN=>"2\0b\0"}, {OUT=>"1 2\0a b\0"}],
|
||||
|
||||
# Specifying a delimiter with a trailing backslash would overrun a
|
||||
# malloc'd buffer.
|
||||
['delim-bs1', q!-d'\'!, {IN=>{'a'x50=>''}}, {EXIT => 1},
|
||||
|
Loading…
Reference in New Issue
Block a user