Awk split string into words and numbers

Viewed 271

I am trying to split of letter and number boundaries, but the solution with lookarounds fails:

echo 50cats30dogs100squirrels | awk '{split($0,a,/(?<=\D)(.*)(?=\d)/); print a[1],a[2],a[3]}'

awk: illegal primary in regular expression (?<=\D)(.*)(?=\d) at <=\D)(.*)(?=\d)
 source line number 1
 context is
     >>> {split($0,a,/(?<=\D)(.*)(?=\d)/) <<<

Is there a way to do this in Awk in other way?

Edit:

Sorry for not being clear. The expected output is to just add spaces like this:

50 cats 30 dogs 100 squirrels
5 Answers

With your shown samples only. Could you please try following, if this is what you are looking for. Written and tested in GNU awk(should work in any awk I believe).

echo "50cats30dogs100squirrels" | awk '{gsub(/[^0-9]+/," & ")} 1'

Output will be as follows for shown samples:

50 cats 30 dogs 100 squirrels

Is there a way to do this in Awk in other way?

I would use GNU AWK for this task following way, let file.txt content be

50cats30dogs100squirrels

then

awk 'BEGIN{FPAT="([[:alpha:]]+)|([[:digit:]]+)"}{$1=$1;print}' file.txt

output

50 cats 30 dogs 100 squirrels

Explanation: I instruct AWK that column is (one or more letters) or (one or more digits) using FPAT. Then I do $1=$1 to cause string rebuilt (without $1=$1; output would be same as input) and print it.

(tested in gawk 4.2.1)

(?<=\D)(.*)(?=\d) is a PCRE. No mandatory Unix tools as defined by the POSIX standard support PCREs. awk in particular supports EREs.

With GNU awk for FPAT:

$ echo '50cats30dogs100squirrels' | awk -v FPAT='[0-9]+|[^0-9]+' '{$1=$1}1'
50 cats 30 dogs 100 squirrels

You could try this:

echo 50cats30dogs100squirrels | awk '{while (match($0, /[0-9]+|[a-zA-Z]+/)) {print substr($0, RSTART, RLENGTH);$0=substr($0, RSTART+RLENGTH)}}'

Which yields:

50
cats
30
dogs
100
squirrels

With gawk, this is a job for gensub, and then split into an array is easier:

gawk '
  BEGIN {
    s = "50cats30dogs100squirrels"
    t = gensub(/[[:alpha:]]+|[[:digit:]]+/, "& ", "g", s)
    print ">" t "<"
    split(t, a)
    for (i in a) print i, a[i]
  }
'

outputs

>50 cats 30 dogs 100 squirrels <
1 50
2 cats
3 30
4 dogs
5 100
6 squirrels
Related