如何在 C 编程 getopt_long 中将转义序列(如制表符和换行符)作为命令行参数传递?

How to pass escape sequence like tab and newline char as command line argument in C programming getopt_long?

我的代码快要结束了,经过大量搜索我没有找到任何解决方案,我想为我的程序提供像'\t'、'\n'这样的转义序列,就像awkperl 程序需要,最后我想将它们用作 printf 或 sprintf 格式字符串

这是我到目前为止尝试过的方法,请注意我需要变量 delim 并且 rs 应该是指针。

 #include <stdio.h>
 #include <stdlib.h>
 #include <getopt.h>


 int main (int argc, char **argv)
 {
   int c;

   char *delim = ",", *rs = "\n\r";

   while (1)
     {
       static struct option long_options[] =
         {

           {"delim",  required_argument, 0, 'd'},
           {"row_sep",  required_argument, 0, 'r'},
           {0, 0, 0, 0}
         };

       int option_index = 0;

       c = getopt_long (argc, argv, "df",
                        long_options, &option_index);


       if (c == -1)
         break;

       switch (c)
         {
         case 0:

           if (long_options[option_index].flag != 0)
             break;
           printf ("option %s", long_options[option_index].name);
           if (optarg)
             printf (" with arg %s", optarg);
           printf ("\n");
           break;

         case 'd':
           delim = optarg;
           break;

         case 'r':
           rs = optarg;
           break;

         case '?':
           break;

         default:
           abort ();
         }
     }


   /* Print any remaining command line arguments (not options). */
   if (optind < argc)
     {
       printf ("non-option ARGV-elements: ");
       while (optind < argc)
         printf ("%s ", argv[optind++]);
       putchar ('\n');
     }



 /* Test input argument */


 printf("This is test%ssome text%s",delim,rs);



   exit (0);
 }

当我编译和执行时,我得到这样的输出

 $ gcc argument.c

 $ ./a.out --delim="\t"
 This is test\tsome text

 $ ./a.out --delim="\t" --row_sep="\n"
 This is test\tsome text\n

我希望它打印制表符和换行符而不是原来的 '\t' 和 '\n'

好心人帮助我。

某些地方的某些代码必须将 backslash-t 和 backslash-n 转换为制表符和换行符。您可以让 shell 执行此操作(如果它是 Bash 或支持 ANSI C quoting):

./a.out --delim=$'\t'
./a.out --delim=$'\t' --row_sep=$'\n'

或使用printf命令(与printf()函数不同,但相关);这避免了使用任何 Bashisms:

./a.out --delim="$(printf '\t')"
./a.out --delim="$(printf '\t')" --row_sep="$(printf '\n')"

或者,实际上,您可以简单地在命令行中键入字符。输入选项卡需要您键入 Control-VControl-I 以避免文件名补全。

$ ./a.out --delim='^V^I'
$ ./a.out --delim='^V^I' --row_sep='
> '

虽然这不太清楚;我会优先使用前两种机制中的一种。

或者你可以在你的程序中完成。这有点难,但并不多。我有一个相当全面的函数,cstrlit_chr() 可以完成大部分工作(它不处理像 \u0123\U00012345 这样的 Unicode 转义),但它不是标准的,它在一个 238 行的文件,其中包含注释和测试代码等(函数中只有 100 non-blank、non-comment 行 C 代码,如果我想花时间,可以压缩一下就可以了),所以这里加起来有点大


Can you please show me cstrlit_chr() example for the same?

记录接口的 header 说:

/* Convert C String Literal in (str..end] (excluding surrounding quotes) */
/* to string, returning length of string, or -1 if conversion error, or */
/* -2 if there is not enough room for the output */
extern int cstrlit_str(const char *str, const char *end, char *buffer, size_t buflen);
/* Convert C Character Literal in (str..end] (excluding surrounding quotes) */
/* to character, returning converted char or -1 if string is invalid. */
/* If non-null, eptr is set to first non-converted (or non-convertible) character */
extern int cstrlit_chr(const char *str, const char *end, char const ** const eptr);

/* Convert character to C Character Literal. */
/* buffer[0] = '[=13=]' if there isn't enough room in buffer */
extern void chr_cstrlit(unsigned char c, char *buffer, size_t buflen);
/* Convert string to C String Literal */
extern void str_cstrlit(const char *str, char *buffer, size_t buflen);

因此,cstrlit_chr() 是一组四个函数中的一个。但是,它非常易于使用:

 const char *endptr;
 int c = cstrlit_char(argv[i], argv[i]+strlen(argv[i]), &endptr);

如果 argv[i] 包含反斜杠和 t,则 c 将被分配 '\t' 的值(通常为 control-I 或 9)。如果它包含反斜杠和 n,那么 c 将被分配 '\n' 的值(通常是 control-J 或 10)。

endptr 中的值告诉您下一个要解释的字符是什么。