0

I'm trying to make a program that reads lines from a file starting at the line that read "bindings: {" and ending with"}", removing colons, commas, and single quotes along the way. Ultimately, I want to save the contents of these lines into different arrays based on what the second field contains.

declare -a text_binding_arr 

gawk '/(bindings: \{)/, /\}/ { 
    gsub(/:/, "")
    gsub(/\047/, "")
    gsub(/\054/, "")

    switch($2) {
        case /=/:
            two_way_binding_arr+=( "$1" )
            break   
        case /\@/:
            text_binding_arr+=( "$1" )
            break
        case /</:
            one_way_binding_arr+=( "$1" )
            break
        case /&/:   
            method_binding_arr+=( "$1" )
            break
        default:
            break
    }
}' test/components/temp."$COMPO".module.js 


for a in text_binding_arr; do echo "${text_binding_arr[@]\n}"; done

Input

templateUrl: 'components/textfield/textfield.template.html',
  controller: bltTextfieldController,
  bindings: {
    model: '=',
    name: '@',
    label: '@',
    type: '@',
    minlength: '<',
    maxlength: '<',
    min: '<',
    max: '<',
    change: '&',
    rows: '<',
    validate: '<',
    required: '<',
    autofocus: '<',
    autocomplete: '<',
    autocorrect: '<',
    spellcheck: '<',
    disabled: '<',
    pattern: '@',
    tabindex: '<',
    step: '<'
  }
};

Expected Output

name
label
type
pattern

What works:

  • finding the pattern (i.e. "bindings: }"}
  • the substitutions
  • printing the array

What doesn't work:

  • switch structure with special characters
  • adding elements to end of arras

It currently outputs a blank line.

I am using Cygwin on Windows 10, if that matters, and the rest of my script works beautifully. This is part of a larger bash script.

I know other people have asked questions about adding to the end of an array in Gawk before here, but none of those solutions are working for me. I have tried all of this and this didn't really apply to me. Any help?

UhHuhOkSure
  • 147
  • 7
  • Please [post sample Input_file with expected output in code tags so that we could help you more on same. – RavinderSingh13 Jul 18 '17 at 17:57
  • Just added everything – UhHuhOkSure Jul 18 '17 at 18:04
  • Could you please add what is the condition/logic/requirement to get only that expected output too here? – RavinderSingh13 Jul 18 '17 at 18:06
  • I'm not quite sure what you mean :( – UhHuhOkSure Jul 18 '17 at 18:07
  • what is the logic behind only getting that output? – RavinderSingh13 Jul 18 '17 at 18:08
  • Different bindings require different treatment. The arrays will be sent to different methods – UhHuhOkSure Jul 18 '17 at 18:12
  • You're confusing awk with shell. Awk and shell are 2 completely different tools, each with their own syntax, semantics, and scope. Your awk code appears to be trying to use shell syntax to try to populate arrays that you declared in shell and are not using in awk. If you show concise, testable sample output and expected output we can help you do whatever it is you're trying to do the right way. – Ed Morton Jul 18 '17 at 18:18
  • This would explain why when I played around with a smaller script, I was able to save to an array. How do I reuse the arrays I make in awk? Or should I try doing everything in Bash again? – UhHuhOkSure Jul 18 '17 at 18:24
  • No, a shell like bash is for manipulating files and process, not for manipulating text. As far as I can tell you should be doing everything in awk. I'll post an awk script that produces the output you want from the input you posted and we can take it from there. – Ed Morton Jul 18 '17 at 18:34

1 Answers1

1
$ cat tst.awk
inBindings {
    gsub(/[:,\047]/,"")
    if ($2 == "=") {
        two_way_binding_arr[++num_two_way_bindings] = $1
    }
    else if ($2 == "@") {
        text_binding_arr[++num_text_bindings] = $1
    }
    else if ($2 == "<") {
        one_way_binding_arr[++num_one_way_bindings] = $1
    }
    else if ($2 == "&") {
        method_binding_arr[++num_method_bindings] = $1
    }
    else {
        exit
    }
}
/^[[:space:]]*bindings:[[:space:]]*{/ {
    inBindings=1
}
END {
    for (i=1; i<=num_text_bindings; i++) {
        print text_binding_arr[i]
    }
}

$ awk -f tst.awk file
name
label
type
pattern

The above will work with any awk on any UNIX box. If you don't actually care about the order that name, label, etc. are printed matching the order they appear in your input then the simpler solution is to just save the $1s as the array indices and visit them with the in operator:

    else if ($2 == "@") {
        text_binding_arr[$1]
    }
    ...
    for (i in text_binding_arr) {
        print i
    }

Also, consider this (using GNU awk for true multi-dimensional arrays):

$ cat tst.awk
inBindings {
    gsub(/[:,\047]/,"")
    if ( $1 == "}" ) {
        exit
    }
    binding_arr[$2][$1]
}
/^\s*bindings:\s*{/ {
    inBindings=1
}
END {
    for (char in binding_arr) {
        print char
        for (val in binding_arr[char]) {
            print "\t" val
        }
    }
}

.

$ awk -f tst.awk file
<
        spellcheck
        autocomplete
        maxlength
        tabindex
        autocorrect
        step
        minlength
        required
        disabled
        rows
        min
        autofocus
        max
        validate
=
        model
&
        change
@
        type
        name
        pattern
        label
Ed Morton
  • 188,023
  • 17
  • 78
  • 185