⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cut.c

📁 linux下一些命令的c语言的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	  break;
	}
      else if (wc == L'\n')
	{
	  putchar ('\n');
	  idx = 0;
	}
      else
	{
	  idx += (operating_mode == byte_mode) ? mblength : 1;
	  if (print_kth (idx))
	    fwrite (bufpos, mblength, sizeof(char), stdout);
	}

      buflen -= mblength;
      bufpos += mblength;
    }
}
#endif
		   
/* Read from stream STREAM, printing to standard output any selected fields.  */

static void
cut_fields (FILE *stream)
{
  int c;
  unsigned int field_idx;
  int found_any_selected_field;
  int buffer_first_field;
  int empty_input;

  found_any_selected_field = 0;
  field_idx = 1;

  c = getc (stream);
  empty_input = (c == EOF);
  if (c != EOF)
    ungetc (c, stream);

  /* To support the semantics of the -s flag, we may have to buffer
     all of the first field to determine whether it is `delimited.'
     But that is unnecessary if all non-delimited lines must be printed
     and the first field has been selected, or if non-delimited lines
     must be suppressed and the first field has *not* been selected.
     That is because a non-delimited line has exactly one field.  */
  buffer_first_field = (suppress_non_delimited ^ !print_kth (1));

  while (1)
    {
      if (field_idx == 1 && buffer_first_field)
	{
	  int len;
	  size_t n_bytes;

	  len = getstr (&field_1_buffer, &field_1_bufsize, stream,
			delim, '\n', 0);
	  if (len < 0)
	    {
	      if (ferror (stream) || feof (stream))
		break;
	      xalloc_die ();
	    }

	  n_bytes = len;
	  assert (n_bytes != 0);

	  /* If the first field extends to the end of line (it is not
	     delimited) and we are printing all non-delimited lines,
	     print this one.  */
	  if ((unsigned char) field_1_buffer[n_bytes - 1] != delim)
	    {
	      if (suppress_non_delimited)
		{
		  /* Empty.  */
		}
	      else
		{
		  fwrite (field_1_buffer, sizeof (char), n_bytes, stdout);
		  /* Make sure the output line is newline terminated.  */
		  if (field_1_buffer[n_bytes - 1] != '\n')
		    putchar ('\n');
		}
	      continue;
	    }
	  if (print_kth (1))
	    {
	      /* Print the field, but not the trailing delimiter.  */
	      fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout);
	      found_any_selected_field = 1;
	    }
	  ++field_idx;
	}

      if (c != EOF)
	{
	  if (print_kth (field_idx))
	    {
	      if (found_any_selected_field)
		{
		  fwrite (output_delimiter_string, sizeof (char),
			  output_delimiter_length, stdout);
		}
	      found_any_selected_field = 1;

	      while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
		{
		  putchar (c);
		}
	    }
	  else
	    {
	      while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
		{
		  /* Empty.  */
		}
	    }
	}

      if (c == '\n')
	{
	  c = getc (stream);
	  if (c != EOF)
	    {
	      ungetc (c, stream);
	      c = '\n';
	    }
	}

      if (c == delim)
	++field_idx;
      else if (c == '\n' || c == EOF)
	{
	  if (found_any_selected_field
	      || (!empty_input && !(suppress_non_delimited && field_idx == 1)))
	    putchar ('\n');
	  if (c == EOF)
	    break;
	  field_idx = 1;
	  found_any_selected_field = 0;
	}
    }
}

#if HAVE_MBRTOWC
static void
cut_fields_mb (FILE *stream)
{
  int c;
  unsigned int field_idx;
  int found_any_selected_field;
  int buffer_first_field;
  int empty_input;
  char buf[MB_LEN_MAX + BUFSIZ];  /* For spooling a read byte sequence. */
  char *bufpos;		/* Next read position of BUF. */
  size_t buflen;	/* The length of the byte sequence in buf. */
  wint_t wc;		/* A gotten wide character. */
  size_t mblength;	/* The byte size of a multibyte character which shows
			   as same character as WC. */
  mbstate_t state;	/* State of the stream. */
  int convfail;		/* 1, when conversion is failed. Otherwise 0. */

  found_any_selected_field = 0;
  field_idx = 1;
  bufpos = buf;
  buflen = 0;
  memset (&state, '\0', sizeof(mbstate_t));

  c = getc (stream);
  empty_input = (c == EOF);
  if (c != EOF)
    ungetc (c, stream);
  else
    wc = WEOF;

  /* To support the semantics of the -s flag, we may have to buffer
     all of the first field to determine whether it is `delimited.'
     But that is unnecessary if all non-delimited lines must be printed
     and the first field has been selected, or if non-delimited lines
     must be suppressed and the first field has *not* been selected.
     That is because a non-delimited line has exactly one field.  */
  buffer_first_field = (suppress_non_delimited ^ !print_kth (1));

  while (1)
    {
      if (field_idx == 1 && buffer_first_field)
	{
	  int len = 0;

	  while (1)
	    {
	      REFILL_BUFFER (buf, bufpos, buflen, stream);

	      GET_NEXT_WC_FROM_BUFFER
		(wc, bufpos, buflen, mblength, state, convfail);

	      if (wc == WEOF)
		break;

	      field_1_buffer = xrealloc (field_1_buffer, len + mblength);
	      memcpy (field_1_buffer + len, bufpos, mblength);
	      len += mblength;
	      buflen -= mblength;
	      bufpos += mblength;

	      if (!convfail && (wc == L'\n' || wc == wcdelim))
		break;
	    }

	  if (wc == WEOF)
	    break;

	  /* If the first field extends to the end of line (it is not
	     delimited) and we are printing all non-delimited lines,
	     print this one.  */
	  if (convfail || (!convfail && wc != wcdelim))
	    {
	      if (suppress_non_delimited)
		{
		  /* Empty.	*/
		}
	      else
		{
		  fwrite (field_1_buffer, sizeof (char), len, stdout);
		  /* Make sure the output line is newline terminated.  */
		  if (convfail || (!convfail && wc != L'\n'))
		    putchar ('\n');
		}
	      continue;
	    }

	  if (print_kth (1))
	    {
	      /* Print the field, but not the trailing delimiter.  */
	      fwrite (field_1_buffer, sizeof (char), len - 1, stdout);
	      found_any_selected_field = 1;
	    }
	  ++field_idx;
	}

      if (wc != WEOF)
	{
	  if (print_kth (field_idx))
	    {
	      if (found_any_selected_field)
		{
		  fwrite (output_delimiter_string, sizeof (char),
			  output_delimiter_length, stdout);
		}
	      found_any_selected_field = 1;
	    }

	  while (1)
	    {
	      REFILL_BUFFER (buf, bufpos, buflen, stream);

	      GET_NEXT_WC_FROM_BUFFER
		(wc, bufpos, buflen, mblength, state, convfail);

	      if (wc == WEOF)
		break;
	      else if (!convfail && (wc == wcdelim || wc == L'\n'))
		{
		  buflen -= mblength;
		  bufpos += mblength;
		  break;
		}

	      if (print_kth (field_idx))
		fwrite (bufpos, mblength, sizeof(char), stdout);

	      buflen -= mblength;
	      bufpos += mblength;
	    }
	}

      if ((!convfail || wc == L'\n') && buflen < 1)
	wc = WEOF;

      if (!convfail && wc == wcdelim)
	++field_idx;
      else if (wc == WEOF || (!convfail && wc == L'\n'))
	{
	  if (found_any_selected_field
	      || (!empty_input && !(suppress_non_delimited && field_idx == 1)))
	    putchar ('\n');
	  if (wc == WEOF)
	    break;
	  field_idx = 1;
	  found_any_selected_field = 0;
	}
    }
}
#endif

static void
cut_stream (FILE *stream)
{
#if HAVE_MBRTOWC
  if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
    {
      switch (operating_mode)
	{
	case byte_mode:
	  if (byte_mode_character_aware)
	    cut_characters_or_cut_bytes_no_split (stream);
	  else
	    cut_bytes (stream);
	  break;

	case character_mode:
	  cut_characters_or_cut_bytes_no_split (stream);
	  break;

	case field_mode:
	  cut_fields_mb (stream);
	  break;

	default:
	  abort ();
	}
    }
  else
#endif
    {
      if (operating_mode == field_mode)
	cut_fields (stream);
      else
	cut_bytes (stream);
    }
}

/* Process file FILE to standard output.
   Return 0 if successful, 1 if not. */

static int
cut_file (char *file)
{
  FILE *stream;

  if (STREQ (file, "-"))
    {
      have_read_stdin = 1;
      stream = stdin;
    }
  else
    {
      stream = fopen (file, "r");
      if (stream == NULL)
	{
	  error (0, errno, "%s", file);
	  return 1;
	}
    }

  cut_stream (stream);

  if (ferror (stream))
    {
      error (0, errno, "%s", file);
      return 1;
    }
  if (STREQ (file, "-"))
    clearerr (stream);		/* Also clear EOF. */
  else if (fclose (stream) == EOF)
    {
      error (0, errno, "%s", file);
      return 1;
    }
  return 0;
}

int
main (int argc, char **argv)
{
  int optc, exit_status = 0;
  int delim_specified = 0;
  char mbdelim[MB_LEN_MAX + 1];
  size_t delimlen = 0;

  program_name = argv[0];
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  atexit (close_stdout);

  operating_mode = undefined_mode;

  /* By default, all non-delimited lines are printed.  */
  suppress_non_delimited = 0;

  delim = '\0';
  have_read_stdin = 0;

  while ((optc = getopt_long (argc, argv, "b:c:d:f:ns", longopts, NULL)) != -1)
    {
      switch (optc)
	{
	case 0:
	  break;

	case 'b':
	  /* Build the byte list. */
	  if (operating_mode != undefined_mode)
	    FATAL_ERROR (_("only one type of list may be specified"));
	  operating_mode = byte_mode;
	  if (set_fields (optarg) == 0)
	    FATAL_ERROR (_("missing list of positions"));
	  break;

	case 'c':
	  /* Build the character list. */
	  if (operating_mode != undefined_mode)
	    FATAL_ERROR (_("only one type of list may be specified"));
	  operating_mode = character_mode;
	  if (set_fields (optarg) == 0)
	    FATAL_ERROR (_("missing list of positions"));
	  break;

	case 'f':
	  /* Build the field list. */
	  if (operating_mode != undefined_mode)
	    FATAL_ERROR (_("only one type of list may be specified"));
	  operating_mode = field_mode;
	  if (set_fields (optarg) == 0)
	    FATAL_ERROR (_("missing list of fields"));
	  break;

	case 'd':
	  /* New delimiter. */
	  /* Interpret -d '' to mean `use the NUL byte as the delimiter.'  */
#if HAVE_MBRTOWC
	    {
	      if(MB_CUR_MAX > 1)
		{
		  mbstate_t state;

		  memset (&state, '\0', sizeof(mbstate_t));
		  delimlen = mbrtowc (&wcdelim, optarg, strnlen(optarg, MB_LEN_MAX), &state);

		  if (delimlen == (size_t)-1 || delimlen == (size_t)-2)
		    ++force_singlebyte_mode;
		  else
		    {
		      delimlen = (delimlen < 1) ? 1 : delimlen;
		      if (wcdelim != L'\0' && *(optarg + delimlen) != '\0')
			FATAL_ERROR (_("the delimiter must be a single character"));
		      memcpy (mbdelim, optarg, delimlen);
		    }
		}

	      if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
#endif
		{
		  if (optarg[0] != '\0' && optarg[1] != '\0')
		    FATAL_ERROR (_("the delimiter must be a single character"));
		  delim = (unsigned char) optarg[0];
		}
	  delim_specified = 1;
	    }
	  break;

	case OUTPUT_DELIMITER_OPTION:
	  /* Interpret --output-delimiter='' to mean
	     `use the NUL byte as the delimiter.'  */
	  output_delimiter_length = (optarg[0] == '\0'
				     ? 1 : strlen (optarg));
	  output_delimiter_string = xstrdup (optarg);
	  break;

	case 'n':
	  byte_mode_character_aware = 1;
	  break;

	case 's':
	  suppress_non_delimited = 1;
	  break;

	case_GETOPT_HELP_CHAR;

	case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);

	default:
	  usage (2);
	}
    }

  if (operating_mode == undefined_mode)
    FATAL_ERROR (_("you must specify a list of bytes, characters, or fields"));

  if (delim_specified && operating_mode != field_mode)
    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\
\tonly when operating on fields"));

  if (!delim_specified)
    {
      delim = '\t';
#ifdef HAVE_MBRTOWC
      wcdelim = L'\t';
      mbdelim[0] = '\t';
      mbdelim[1] = '\0';
      delimlen = 1;
#endif
    }

  if (output_delimiter_string == NULL)
    {
#ifdef HAVE_MBRTOWC
      if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
	{
	  output_delimiter_string = xstrdup(mbdelim);
	  output_delimiter_length = delimlen;
	}

      if (MB_CUR_MAX <= 1 || force_singlebyte_mode)
#endif
	{
	  static char dummy[2]; 
	  dummy[0] = delim;
	  dummy[1] = '\0';
	  output_delimiter_string = dummy;
	  output_delimiter_length = 1;
	}
    }

  if (optind == argc)
    exit_status |= cut_file ("-");
  else
    for (; optind < argc; optind++)
      exit_status |= cut_file (argv[optind]);

  if (have_read_stdin && fclose (stdin) == EOF)
    {
      error (0, errno, "-");
      exit_status = 1;
    }

  exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -