shellawkopenscad

Parse a line of pairs of delimited string and construct new command


I have this line as one of many in a file

show = "holder";  // [holder: Dispensor,dryer: Hair Dryer,bidet: Bedit,cover: Cover,wall mount: Wall Mount,screwdriver cutout: Screwdriver Cutout, assembly: Assembly,exploded: Exploded,vitamin: Vitamin]

What I want is to generate a shell script file where for each xxx:yyy pair generate the following line:

openscad --quite --export-format --D 'show=xxx' binstl -o xxx.stl $1

The $1 above is for the first parameter of a shell script.

I have tried this code:

match($0, /\[[^\n\]]*\]$/) {                # get [xx:yy, aa:bb]
    s = substr($0, RSTART+1, RLENGTH-2);    # strip the [ and ]
    n = split(s, arr,",");                  # split the pairs
    for(x in arr) {                         # for each pair
        match(arr[x], /([^\n:]+)/, b) {     # get the first field of the pair
            print subsgtr(b[1], RSTART, RLENGTH)
        }
    }
}

With this result:

gawk: prog:5:       match(arr[x], /([^\n:]+)/, b) {     # get the first field of the pair
gawk: prog:5:                                     ^ syntax error

I've also tried this:

    match($0, /\[[^\n\]]*\]$/) {                # get [xx:yy, aa:bb]
        s = substr($0, RSTART+1, RLENGTH-2);    # strip the [ and ]
        n = split(s, arr,",");                  # split the pairs
        for(x in arr) {                         # for each pair
            arr[x] ~ /([^\n:]+)/ print 
        }
    }

gawk: prog:5:       arr[x] ~ /([^\n:]+)/ print 
gawk: prog:5:                            ^ syntax error

and this:

match($0, /\[[^\n\]]*\]$/) {                # get [xx:yy, aa:bb]
    s = substr($0, RSTART+1, RLENGTH-2);    # strip the [ and ]
    n = split(s, arr,",");                  # split the pairs
    for(x in arr) {                         # for each pair
        arr[x] ~ /([^\n:]+)/ { print }
    }
}

gawk: prog:5:       arr[x] ~ /([^\n:]+)/ { print }
gawk: prog:5:                            ^ syntax error

I don't understand why I'm getting the syntax errors. If you show me a different/better solution, if you can, please explain the syntax errors so I can learn more about awk. Thanks!


Solution

  • awk pattern-action statements are expressed as condition {action}. You cannot use the same pattern-action form inside an action. Use if statements, instead. For instance, replace arr[x] ~ /([^\n:]+)/ print with if(arr[x] ~ /([^\n:]+)/) print.

    For your problem, and with the given example, you could define the input field separator as a regular expression, and skip the first and last fields. Example, with quotes added compared with the expected output (because you have some spaces there), and 2 typos fixed (quiet and --export-format binstl):

    $ cmd="openscad --quiet --export-format binstl --D 'show=X' -o 'X.stl' \"\$1\""
    $ awk -F '[[:space:]]*(.*[[]|:[^,]*[],])[[:space:]]*' -v cmd="$cmd" '
      {for(i = 2; i < NF; i++) {c=cmd; gsub(/X/,$i,c); print c}}' file
    openscad --quiet --export-format binstl --D 'show=holder' -o 'holder.stl' "$1"
    openscad --quiet --export-format binstl --D 'show=dryer' -o 'dryer.stl' "$1"
    openscad --quiet --export-format binstl --D 'show=bidet' -o 'bidet.stl' "$1"
    openscad --quiet --export-format binstl --D 'show=cover' -o 'cover.stl' "$1"
    openscad --quiet --export-format binstl --D 'show=wall mount' -o 'wall mount.stl' "$1"
    openscad --quiet --export-format binstl --D 'show=screwdriver cutout' -o 'screwdriver cutout.stl' "$1"
    openscad --quiet --export-format binstl --D 'show=assembly' -o 'assembly.stl' "$1"
    openscad --quiet --export-format binstl --D 'show=exploded' -o 'exploded.stl' "$1"
    openscad --quiet --export-format binstl --D 'show=vitamin' -o 'vitamin.stl' "$1"
    

    Note: another approach would be to write a generic bash script in which you use awk to feed a loop. In the following example the input file is passed as second parameter ($2):

    #!/usr/bin/env bash
    
    if (( $# != 2 )); then
      printf 'usage: %s ARG FILE\n' "${0##*/}"
      exit 1
    elif ! [[ -f "$2" ]]; then
      printf '%s: file not found\n' "$2"
      exit 1
    fi
    awk -F '[[:space:]]*(.*[[]|:[^,]*[],])[[:space:]]*' '
      {for(i = 2; i < NF; i++) print $i}' "$2" | while read -r s; do
      openscad --quiet --export-format binstl --D "show=$s" -o "$s.stl" "$1"
    done