0

Given a file containing many lines such as, e.g.:

Z|X|20210903|07:00:00|S|33|27.71||

With wanted output of, e.g.:

Z|X|20210903|07:00:00|S|33|27.71|||03-09-2021 07:00:00

This GNU awk command works:

gawk -F'|' '{dt = gensub(/(....)(..)(..)/,"\\3-\\2-\\1",1,$3); print $0"|"dt,$4}' infile > outfile

However, I need this to work under macOS with the version of awk that is installed by default, and it produces the following error:

awk: calling undefined function gensub
 input record number 1, file 
 source line number 1

I'm assuming the default version of awk in macOS is too old and doesn't support the gensub function.

Note that I have tried numerous other string functions to no avail. awk programming is not in my area of expertise and I derived at the GNU awk command above thru a fair amount of googling, but my google-fu was unsuccessful in trying to get something to work with macOS awk.

Can the above GNU awk command be rewritten to work with the default version of awk in, e.g., macOS Catalina and if so how?

2
  • 1
    have you tried brew install gawk ? Commented Sep 22, 2021 at 0:47
  • @Diego Torres Milano, RE: "have you tried brew install gawk ?" -- Thanks for your comment, however, maybe you didn't see where I stated "However, I need this to work under macOS with the version of awk that is installed by default", ... so installing Homebrew and its requirements is not an option unless it cannot be done in some similar way with the version of awk that is installed by default in macOS. Commented Sep 22, 2021 at 0:55

2 Answers 2

3

Would you please try the following:

awk -F'|' '{dt=substr($3,7,2) "-" substr($3,5,2) "-" substr($3,1,4); print $0 "|" dt, $4}' infile > outfile
Sign up to request clarification or add additional context in comments.

3 Comments

tshiono, I think my failure was it trying to retain the use of capture groups and didn't even think to use multiple substr functions, +1 and will wait a while to see if any other answers come in before marking one as the accepted answer.
user3439894 nothing in POSIX awk (including MacOS/BSD awk) supports capture groups, that's why the GNU awk guys had to invent gensub() and the 3rd arg to match() and the 4th arg to split()and patsplit(). MacOS awk doesn't support any of those but it's not because the version is too old, it's because those are all GNU extensions, they simply aren't part of the POSIX spec. What @tshiono shows in their answer is the best POSIX equivalent of the GNU code in your question and will work in any awk, even non-POSIX ones.
@Ed Morton, I very much appreciate the information presented in your comment, it makes sense, thanks!
0

Using perl instead of gawk:

$ perl -lne '
   my @F = split /[|]/, $_, -1;
   my $dt = ($F[2] =~ s/(....)(..)(..)/$3-$2-$1/r);
   print join("|", @F, "$dt $F[3]")' <<<"Z|X|20210903|07:00:00|S|33|27.71||"
Z|X|20210903|07:00:00|S|33|27.71|||03-09-2021 07:00:00

1 Comment

Shawn, This does work, although I'd rather use awk, but it's worth a +1.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.