logo

utils-std

Collection of commonly available Unix tools
commit: e347dbeed068198522c58c9ea5785477e17be282
parent 5e0d5c0545d8de4b3a177a09a7e0e4038f33910e
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat, 24 Aug 2024 06:45:58 +0200

cmd/cut: support -d ''

Diffstat:

Mcmd/cut.15+++--
Mcmd/cut.c32+++++++++++++++++++-------------
Mtest-cmd/cut.sh25++++++++++++++++++++++++-
3 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/cmd/cut.1 b/cmd/cut.1 @@ -49,8 +49,9 @@ Cut codepoints based on .Ar list . .It Fl d Ar delim Set the field delimiter to the character -.Ar delim . -(default: \t) +.Ar delim , +if an empty string is passed, then NULL is used as separator. +(default:\ \et) .It Fl f Ar list Cut fields based on .Ar list . diff --git a/cmd/cut.c b/cmd/cut.c @@ -286,13 +286,23 @@ cut_f(FILE *in, const char *filename) if(line[nread - 1] == '\n') line[--nread] = '\0'; - if(opt_s && strchr(line, delim) == NULL) continue; + if(opt_s) + { + size_t i = 0; + for(; i < (size_t)nread; i++) + if(line[i] == delim) break; + + if(i == (size_t)nread) continue; + } bool need_sep = false; - size_t i = 0; - char *toks = NULL; - for(char *c = strtok_r(line, &delim, &toks); c != NULL; c = strtok_r(NULL, &delim, &toks), i++) + char *c = line; + for(size_t pos = 0, i = 0; pos <= (size_t)nread; pos++) { + if(pos < (size_t)nread && line[pos] != delim) continue; + + line[pos] = '\0'; + if(i >= list_len) { if(!nostop) break; @@ -301,16 +311,17 @@ cut_f(FILE *in, const char *filename) fputs(c, stdout); need_sep = true; - continue; } - - if(list[i]) + else if(list[i]) { if(need_sep) fputc(delim, stdout); fputs(c, stdout); need_sep = true; } + + i++; + c = line + pos + 1; } fputc('\n', stdout); @@ -386,12 +397,7 @@ main(int argc, char *argv[]) opt_list = optarg; break; case 'd': - if(optarg[0] == '\0') - { - fprintf(stderr, "cut: Option '-d' requires a character, got an empty string\n"); - return 1; - } - if(optarg[1] != '\0') + if(optarg[0] != '\0' && optarg[1] != '\0') { fprintf(stderr, "cut: Option '-d' only accepts single characters, got \"%s\"\n", optarg); return 1; diff --git a/test-cmd/cut.sh b/test-cmd/cut.sh @@ -4,10 +4,27 @@ WD="$(dirname "$0")/../" target="${WD}/cmd/cut" -plans=12 +plans=15 . "${WD}/test-cmd/tap.sh" . "${WD}/test-cmd/init_env.sh" +t_null_f2() +{ + name="null_f2" + exp="_2" + + count=$((count+1)) + out="$("$target" -d '' -f2 "${WD}/test-cmd/inputs/strings/length" 2>&1)" + ret="$?" + if [ "$?" != 0 ]; then + printf 'not ok %s - %s\n' "$count $name" "$out" + elif [ "$out" != "$exp" ]; then + printf 'not ok %s - (%s != %s)\n' "$count $name" "$out" "$exp" + else + printf 'ok %s\n' "$count $name" + fi +} + t 'bytes:2-3,10-20,4,12' "-b 2-3,10-20,4,12 ${WD}/test-cmd/inputs/alnum" '1239ABCDEFGHIJ ' t 'bytes:11-' "-b 11- ${WD}/test-cmd/inputs/alnum" 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz @@ -49,3 +66,9 @@ t --input="$fields" f-2 '-f-2' '1 2 a b ' + +t --input="hello" 'hello_f1' '-f1' 'hello +' +t --input="hello" 'hello_f1_s' '-f1 -s' + +t_null_f2