bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

have cut -c print output-delimiter


From: Jan Nieuwenhuizen
Subject: have cut -c print output-delimiter
Date: Mon Dec 2 20:16:01 2002
User-agent: Gnus/5.090008 (Oort Gnus v0.08) Emacs/21.2 (i386-pc-linux-gnu)

Hi,

Find a patch below that makes cut print output-delimiter when working
on byte ranges, but only if output-delimiter was explicitely specified
on the command line.

>From cut --help, one would already expect cut to handle this case,
which is very useful to (pre)process fixed-width text tables.

Greetings,
Jan.

PS: I checked subversions.gnu.org:cvsroot/textutils and
    :cvsroot/coreutils first and found both modules to exist, but
    empty.  A README redirecting the user to alpha.gnu.org would be
    most friendly.

Example:
    ls -l | cut --output-delimiter=, -c1,2-4,5-7,8-10,57- > foo
    mysql -e 'create table foo (d char(1),u char(3), g varchar (3), o \
        varchar (3), n text)' test
    mysqlimport --fields-terminated-by=, test foo


ChangeLog:    
2002-12-02  Jan Nieuwenhuizen  <address@hidden>

        * src/cut.c (print_kth): Also return whether char is first of
        range or field.
        (set_fields): Mark start of field or range.
        (cut_bytes): If user specified output_delimiter, output
        output_delimiter_string between ranges.
        (main): Initialize new file-scope global
        output_delimiter_specified.

        
diff -p'urNx*~' -x'ChangeLog*' ../coreutils-4.5.3/src/cut.c ./src/cut.c
--- ../coreutils-4.5.3/src/cut.c        2002-10-13 16:03:06.000000000 +0200
+++ ./src/cut.c 2002-12-02 14:58:27.000000000 +0100
@@ -126,6 +126,9 @@ static int suppress_non_delimited;
 /* The delimeter character for field mode. */
 static int delim;
 
+/* Was output_delimiter specified?  */
+static int output_delimiter_specified;
+
 /* The length of output_delimiter_string.  */
 static size_t output_delimiter_length;
 
@@ -210,11 +213,19 @@ With no FILE, or when FILE is -, read st
   exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
+/* Return nonzero if k is printable, 2 for first position in range or
+   field, 1 for other positions. */
+
 static int
 print_kth (unsigned int k)
 {
-  return ((0 < eol_range_start && eol_range_start <= k)
-         || (k <= max_range_endpoint && printable_field[k]));
+  if (eol_range_start > 0 && k >= eol_range_start)
+    return 1 + (eol_range_start == k);
+  
+  if (k <= max_range_endpoint)
+    return printable_field[k];
+  
+  return 0;
 }
 
 /* Given the list of field or byte range specifications FIELDSTR, set
@@ -371,8 +382,12 @@ set_fields (const char *fieldstr)
   /* Set the array entries corresponding to integers in the ranges of RP.  */
   for (i = 0; i < n_rp; i++)
     {
-      unsigned int j;
-      for (j = rp[i].lo; j <= rp[i].hi; j++)
+      unsigned int j = rp[i].lo;
+
+      /* Mark first position of field or range with a 2. */
+      if (j <= rp[i].hi)
+       printable_field[j] = 2;
+      for (++j; j <= rp[i].hi; j++)
        {
          printable_field[j] = 1;
        }
@@ -389,8 +404,10 @@ static void
 cut_bytes (FILE *stream)
 {
   unsigned int byte_idx;       /* Number of chars in the line so far. */
-
+  int found_any_selected_range; /* Was a range output in the line so far.  */
+    
   byte_idx = 0;
+  found_any_selected_range = 0;
   while (1)
     {
       register int c;          /* Each character from the file. */
@@ -401,6 +418,7 @@ cut_bytes (FILE *stream)
        {
          putchar ('\n');
          byte_idx = 0;
+         found_any_selected_range = 0;
        }
       else if (c == EOF)
        {
@@ -410,16 +428,22 @@ cut_bytes (FILE *stream)
        }
       else
        {
-         ++byte_idx;
-         if (print_kth (byte_idx))
+         int idx_status = print_kth (++byte_idx);
+         if (idx_status)
            {
+             if (idx_status == 2 && found_any_selected_range
+                 && output_delimiter_specified)
+               fwrite (output_delimiter_string, sizeof (char),
+                       output_delimiter_length, stdout);
+             found_any_selected_range = 1;
              putchar (c);
            }
        }
     }
 }
 
-/* Read from stream STREAM, printing to standard output any selected fields.  
*/
+/* Read from stream STREAM, printing to standard output any selected
+   fields.  */
 
 static void
 cut_fields (FILE *stream)
@@ -611,6 +635,7 @@ main (int argc, char **argv)
 
   delim = '\0';
   have_read_stdin = 0;
+  output_delimiter_specified = 0;
 
   while ((optc = getopt_long (argc, argv, "b:c:d:f:ns", longopts, NULL)) != -1)
     {
@@ -648,6 +673,7 @@ main (int argc, char **argv)
          break;
 
        case OUTPUT_DELIMITER_OPTION:
+         output_delimiter_specified = 1;
          /* Interpret --output-delimiter='' to mean
             `use the NUL byte as the delimiter.'  */
          output_delimiter_length = (optarg[0] == '\0'
@@ -675,7 +701,8 @@ main (int argc, char **argv)
     FATAL_ERROR (_("you must specify a list of bytes, characters, or fields"));
 
   if (delim != '\0' && operating_mode != field_mode)
-    FATAL_ERROR (_("a delimiter may be specified only when operating on 
fields"));
+    FATAL_ERROR (_("a delimiter may be specified only when operating on \
+fields"));
 
   if (suppress_non_delimited && operating_mode != field_mode)
     FATAL_ERROR (_("suppressing non-delimited lines makes sense\n\


-- 
Jan Nieuwenhuizen <address@hidden> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org





reply via email to

[Prev in Thread] Current Thread [Next in Thread]