From a208fa03de8467d1f51821f874cbf142aaad74fa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Dec 2024 18:49:10 +0100 Subject: [PATCH] cut: implement --output-delimiter function old new delta cut_main 1204 1261 +57 static.cut_longopts - 20 +20 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/0 up/down: 77/0) Total: 77 bytes Signed-off-by: Denys Vlasenko --- coreutils/cut.c | 27 +++++++++++++++++++++++++-- testsuite/cut.tests | 32 ++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/coreutils/cut.c b/coreutils/cut.c index f4d930db0..9f5b649d8 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c @@ -107,6 +107,7 @@ static void cut_file(FILE *file, const char *delim, const char *odelim, /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ if (option_mask32 & (OPT_CHAR | OPT_BYTE)) { char *printed = xzalloc(linelen + 1); + int need_odelim = 0; /* print the chars specified in each cut list */ for (; cl_pos < nlists; cl_pos++) { @@ -114,9 +115,14 @@ static void cut_file(FILE *file, const char *delim, const char *odelim, for (spos = cut_list[cl_pos].startpos; spos < linelen;) { if (!printed[spos]) { printed[spos] = 'X'; + if (need_odelim && spos != 0 && !printed[spos-1]) { + need_odelim = 0; + fputs_stdout(odelim); + } putchar(line[spos]); } if (++spos > cut_list[cl_pos].endpos) { + need_odelim = (odelim && odelim[0]); /* will print OSEP (if not empty) */ break; } } @@ -165,6 +171,9 @@ static void cut_file(FILE *file, const char *delim, const char *odelim, goto next_line; } + if (!odelim) + odelim = "\t"; + /* Loop through bytes, finding next delimiter */ for (;;) { /* End of current range? */ @@ -257,17 +266,31 @@ int cut_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_CUT_REGEX regex_t reg; #endif +#if ENABLE_LONG_OPTS + static const char cut_longopts[] ALIGN1 = + "output-delimiter\0" Required_argument "O" + ; +#endif #define ARG "bcf"IF_FEATURE_CUT_REGEX("F") +#if !ENABLE_LONG_OPTS opt = getopt32(argv, "^" OPT_STR // = "b:c:f:d:O:sD"IF_FEATURE_CUT_REGEX("F:")"n" "\0" "b--"ARG":c--"ARG":f--"ARG IF_FEATURE_CUT_REGEX("F--"ARG), &sopt, &sopt, &sopt, &delim, &odelim IF_FEATURE_CUT_REGEX(, &sopt) ); - if (!delim || !*delim) - delim = (opt & OPT_REGEX) ? "[[:space:]]+" : "\t"; +#else + opt = getopt32long(argv, "^" + OPT_STR // = "b:c:f:d:O:sD"IF_FEATURE_CUT_REGEX("F:")"n" + "\0" "b--"ARG":c--"ARG":f--"ARG IF_FEATURE_CUT_REGEX("F--"ARG), + cut_longopts, + &sopt, &sopt, &sopt, &delim, &odelim IF_FEATURE_CUT_REGEX(, &sopt) + ); +#endif if (!odelim) odelim = (opt & OPT_REGEX) ? " " : delim; + if (!delim || !*delim) + delim = (opt & OPT_REGEX) ? "[[:space:]]+" : "\t"; // argc -= optind; argv += optind; diff --git a/testsuite/cut.tests b/testsuite/cut.tests index 46ef545d7..ba5f88d60 100755 --- a/testsuite/cut.tests +++ b/testsuite/cut.tests @@ -23,14 +23,30 @@ the quick brown fox jumps over the lazy dog testing "cut -b a,a,a" "cut -b 3,3,3 input" "e\np\ne\n" "$abc" "" -testing "cut -b overlaps" "cut -b 1-3,2-5,7-9,9-10 input" \ - "one:to:th\nalphabeta\nthe qick \n" "$abc" "" -testing "-b encapsulated" "cut -b 3-8,4-6 input" "e:two:\npha:be\ne quic\n" \ - "$abc" "" -# --output-delimiter not implemnted (yet?) -#testing "cut -bO overlaps" \ -# "cut --output-delimiter ' ' -b 1-3,2-5,7-9,9-10 input" \ -# "one:t o:th\nalpha beta\nthe q ick \n" "$abc" "" +testing "cut -b overlaps" \ + "cut -b 1-3,2-5,7-9,9-10 input" \ + "\ +one:to:th +alphabeta +the qick \n" \ + "$abc" "" +testing "-b encapsulated" \ + "cut -b 3-8,4-6 input" \ + "\ +e:two: +pha:be +e quic\n" \ + "$abc" "" +optional LONG_OPTS +testing "cut -b --output-delimiter overlaps" \ + "cut --output-delimiter='^' -b 1-3,2-5,7-9,9-10 input" \ + "\ +one:t^o:th +alpha^beta +the q^ick \n" \ + "$abc" "" +SKIP= + testing "cut high-low error" "cut -b 8-3 input 2>/dev/null || echo err" "err\n" \ "$abc" ""