1

I know this question has been answered many times like here and here.

But all of them had places where there was an extra erroneous quote.

I am just running a simple awk script in this fashion:

awk -f test.awk -v time="$t" copy.out

Now when I type until

awk -f test.awk -v time="$t" c #Press Tab after c

And press tab for tab completion I get the error:

awk -f test.awk -v time="$t" cbash: unexpected EOF while looking for matching `"'
bash: syntax error: unexpected end of file

I have the appropriate number of double quotes in my command. I know this for sure because if I type out my file name without tab completion and then execute the command then it works fine.

What am I missing ?

When I run bash -x and then do the above mentioned steps I get :

word split
+ _init_completion -s
+ local exclude= flag outx errx inx OPTIND=1
+ getopts n:e:o:i:s flag -s
+ case $flag in
+ split=false
+ exclude+==
+ getopts n:e:o:i:s flag -s
+ COMPREPLY=()
+ local 'redir=@(?([0-9])<|?([0-9&])>?(>)|>&)'
+ _get_comp_words_by_ref -n '=<>&' cur prev words cword
+ local exclude flag i OPTIND=1
+ words=()
+ local cur cword words
+ upargs=()
+ upvars=()
+ local upargs upvars vcur vcword vprev vwords
+ getopts c:i:n:p:w: flag -n '=<>&' cur prev words cword
+ case $flag in
+ exclude='=<>&'
+ getopts c:i:n:p:w: flag -n '=<>&' cur prev words cword
+ [[ 6 -ge 3 ]]
+ case ${!OPTIND} in
+ vcur=cur
+ let 'OPTIND += 1'
+ [[ 6 -ge 4 ]]
+ case ${!OPTIND} in
+ vprev=prev
+ let 'OPTIND += 1'
+ [[ 6 -ge 5 ]]
+ case ${!OPTIND} in
+ vwords=words
+ let 'OPTIND += 1'
+ [[ 6 -ge 6 ]]
+ case ${!OPTIND} in
+ vcword=cword
+ let 'OPTIND += 1'
+ [[ 6 -ge 7 ]]
+ __get_cword_at_cursor_by_ref '=<>&' words cword cur
+ words=()
+ local cword words
+ __reassemble_comp_words_by_ref '=<>&' words cword
+ local exclude i j line ref
+ [[ -n =<>& ]]
+ exclude='=<>&'
+ printf -v cword %s 6
+ [[ -n =<>& ]]
+ line='awk -f test.awk -v time="$t" c'
+ (( i=0, j=0 ))
+ (( i < 7 ))
+ [[ 0 -gt 0 ]]
+ ref='words[0]'
+ printf -v 'words[0]' %s awk
+ line=' -f test.awk -v time="$t" c'
+ [[ 0 == 6 ]]
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 1 -gt 0 ]]
+ [[ -f == +([=<>&]) ]]
+ ref='words[1]'
+ printf -v 'words[1]' %s -f
+ line=' test.awk -v time="$t" c'
+ [[ 1 == 6 ]]
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 2 -gt 0 ]]
+ [[ test.awk == +([=<>&]) ]]
+ ref='words[2]'
+ printf -v 'words[2]' %s test.awk
+ line=' -v time="$t" c'
+ [[ 2 == 6 ]]
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 3 -gt 0 ]]
+ [[ -v == +([=<>&]) ]]
+ ref='words[3]'
+ printf -v 'words[3]' %s -v
+ line=' time="$t" c'
+ [[ 3 == 6 ]]
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 4 -gt 0 ]]
+ [[ time == +([=<>&]) ]]
+ ref='words[4]'
+ printf -v 'words[4]' %s time
+ line='="$t" c'
+ [[ 4 == 6 ]]
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 5 -gt 0 ]]
+ [[ =" == +([=<>&]) ]]
+ ref='words[5]'
+ printf -v 'words[5]' %s '="'
+ line='$t" c'
+ [[ 5 == 6 ]]
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 6 -gt 0 ]]
+ [[ $t" c == +([=<>&]) ]]
+ ref='words[6]'
+ printf -v 'words[6]' %s '$t" c'
+ line=
+ [[ 6 == 6 ]]
+ printf -v cword %s 6
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 7 == 6 ]]
+ local i cur index=30 'lead=awk -f test.awk -v time="$t" c'
+ [[ 30 -gt 0 ]]
+ [[ -n awk -f test.awk -v time="$t" c ]]
+ [[ -n awk-ftest.awk-vtime="$t"c ]]
+ cur='awk -f test.awk -v time="$t" c'
+ (( i = 0 ))
+ (( i <= cword ))
+ [[ 30 -ge 3 ]]
+ [[ awk != \a\w\k ]]
+ [[ 0 -lt 6 ]]
+ local old_size=30
+ cur=' -f test.awk -v time="$t" c'
+ local new_size=27
+ index=27
+ (( ++i  ))
+ (( i <= cword ))
+ [[ 27 -ge 2 ]]
+ [[  - != \-\f ]]
+ cur='-f test.awk -v time="$t" c'
+ [[ 27 -gt 0 ]]
+ (( index-- ))
+ [[ 26 -ge 2 ]]
+ [[ -f != \-\f ]]
+ [[ 1 -lt 6 ]]
+ local old_size=26
+ cur=' test.awk -v time="$t" c'
+ local new_size=24
+ index=24
+ (( ++i  ))
+ (( i <= cword ))
+ [[ 24 -ge 8 ]]
+ [[  test.aw != \t\e\s\t\.\a\w\k ]]
+ cur='test.awk -v time="$t" c'
+ [[ 24 -gt 0 ]]
+ (( index-- ))
+ [[ 23 -ge 8 ]]
+ [[ test.awk != \t\e\s\t\.\a\w\k ]]
+ [[ 2 -lt 6 ]]
+ local old_size=23
+ cur=' -v time="$t" c'
+ local new_size=15
+ index=15
+ (( ++i  ))
+ (( i <= cword ))
+ [[ 15 -ge 2 ]]
+ [[  - != \-\v ]]
+ cur='-v time="$t" c'
+ [[ 15 -gt 0 ]]
+ (( index-- ))
+ [[ 14 -ge 2 ]]
+ [[ -v != \-\v ]]
+ [[ 3 -lt 6 ]]
+ local old_size=14
+ cur=' time="$t" c'
+ local new_size=12
+ index=12
+ (( ++i  ))
+ (( i <= cword ))
+ [[ 12 -ge 4 ]]
+ [[  tim != \t\i\m\e ]]
+ cur='time="$t" c'
+ [[ 12 -gt 0 ]]
+ (( index-- ))
+ [[ 11 -ge 4 ]]
+ [[ time != \t\i\m\e ]]
+ [[ 4 -lt 6 ]]
+ local old_size=11
+ cur='="$t" c'
+ local new_size=7
+ index=7
+ (( ++i  ))
+ (( i <= cword ))
+ [[ 7 -ge 2 ]]
+ [[ =" != \=\" ]]
+ [[ 5 -lt 6 ]]
+ local old_size=7
+ cur='$t" c'
+ local new_size=5
+ index=5
+ (( ++i  ))
+ (( i <= cword ))
+ [[ 5 -ge 5 ]]
+ [[ $t" c != \$\t\"\ \c ]]
+ [[ 6 -lt 6 ]]
+ (( ++i  ))
+ (( i <= cword ))
+ [[ -n $t" c ]]
+ [[ ! -n $t"c ]]
+ [[ 5 -lt 0 ]]
+ local words cword cur
+ _upvars -a7 words awk -f test.awk -v time '="' '$t" c' -v cword 6 -v cur '$t" c'
+ ((  15  ))
+ ((  15  ))
+ case $1 in
+ [[ -n 7 ]]
+ printf %d 7
+ [[ -n words ]]
+ unset -v words
+ eval 'words=("${@:3:7}")'
++ words=("${@:3:7}")
+ shift 9
+ ((  6  ))
+ case $1 in
+ [[ -n cword ]]
+ unset -v cword
+ eval 'cword="$3"'
++ cword=6
+ shift 3
+ ((  3  ))
+ case $1 in
+ [[ -n cur ]]
+ unset -v cur
+ eval 'cur="$3"'
++ cur='$t" c'
+ shift 3
+ ((  0  ))
+ [[ -n cur ]]
+ upvars+=("$vcur")
+ upargs+=(-v $vcur "$cur")
+ [[ -n cword ]]
+ upvars+=("$vcword")
+ upargs+=(-v $vcword "$cword")
+ [[ -n prev ]]
+ [[ 6 -ge 1 ]]
+ upvars+=("$vprev")
+ upargs+=(-v $vprev "${words[cword - 1]}")
+ [[ -n words ]]
+ upvars+=("$vwords")
+ upargs+=(-a${#words[@]} $vwords "${words[@]}")
+ ((  4  ))
+ local cur cword prev words
+ _upvars -v cur '$t" c' -v cword 6 -v prev '="' -a7 words awk -f test.awk -v time '="' '$t" c'
+ ((  18  ))
+ ((  18  ))
+ case $1 in
+ [[ -n cur ]]
+ unset -v cur
+ eval 'cur="$3"'
++ cur='$t" c'
+ shift 3
+ ((  15  ))
+ case $1 in
+ [[ -n cword ]]
+ unset -v cword
+ eval 'cword="$3"'
++ cword=6
+ shift 3
+ ((  12  ))
+ case $1 in
+ [[ -n prev ]]
+ unset -v prev
+ eval 'prev="$3"'
++ prev='="'
+ shift 3
+ ((  9  ))
+ case $1 in
+ [[ -n 7 ]]
+ printf %d 7
+ [[ -n words ]]
+ unset -v words
+ eval 'words=("${@:3:7}")'
++ words=("${@:3:7}")
+ shift 9
+ ((  0  ))
+ _variables
+ [[ $t" c =~ ^(\$(\{[!#]?)?)([A-Za-z0-9_]*)$ ]]
+ [[ $t" c =~ ^(\$\{[#!]?)([A-Za-z0-9_]*)\[([^]]*)$ ]]
+ [[ $t" c =~ ^\$\{[#!]?[A-Za-z0-9_]*\[.*]$ ]]
+ case $prev in
+ return 1
+ [[ $t" c == @(?([0-9])<|?([0-9&])>?(>)|>&)* ]]
+ [[ =" == @(?([0-9])<|?([0-9&])>?(>)|>&) ]]
+ local i skip
+ (( i=1 ))
+ (( i < 7 ))
+ [[ -f == @(?([0-9])<|?([0-9&])>?(>)|>&)* ]]
+ i=2
+ (( 1 ))
+ (( i < 7 ))
+ [[ test.awk == @(?([0-9])<|?([0-9&])>?(>)|>&)* ]]
+ i=3
+ (( 1 ))
+ (( i < 7 ))
+ [[ -v == @(?([0-9])<|?([0-9&])>?(>)|>&)* ]]
+ i=4
+ (( 1 ))
+ (( i < 7 ))
+ [[ time == @(?([0-9])<|?([0-9&])>?(>)|>&)* ]]
+ i=5
+ (( 1 ))
+ (( i < 7 ))
+ [[ =" == @(?([0-9])<|?([0-9&])>?(>)|>&)* ]]
+ i=6
+ (( 1 ))
+ (( i < 7 ))
+ [[ $t" c == @(?([0-9])<|?([0-9&])>?(>)|>&)* ]]
+ i=7
+ (( 1 ))
+ (( i < 7 ))
+ [[ 6 -le 0 ]]
+ prev='="'
+ [[ -n false ]]
+ _split_longopt
+ [[ $t" c == --?*=* ]]
+ return 1
+ return 0
+ case "${prev,,}" in
+ false
+ [[ $t" c == -* ]]
+ [[ awk == @(rmdir|chroot) ]]
+ [[ awk == mkdir ]]
+ _filedir
+ local 'IFS=
'
+ _tilde '$t" c'
+ local result=0
+ [[ $t" c == \~* ]]
+ return 0
+ local -a toks
+ local x tmp
++ compgen -d -- '$t" c'
+ x=
+ [[ '' != -d ]]
+ local quoted
+ _quote_readline_by_ref '$t" c' quoted
+ '[' -z '$t" c' ']'
+ [[ $t" c == \'* ]]
+ [[ $t" c == \~* ]]
+ printf -v quoted %q '$t" c'
+ [[ \$t\"\ c == *\\* ]]
+ printf -v quoted %s '$t" c'
+ [[ $t" c == \$* ]]
+ eval 'quoted=$t" c'
bash: unexpected EOF while looking for matching `"'
bash: syntax error: unexpected end of file
+ local xspec=
++ compgen -f -X '' -- '$t" c'
+ x=
+ [[ -n '' ]]
+ [[ 0 -ne 0 ]]

The last lines it says unquoted $t" but I do provide the full quotes and it does work. So isn't this some kind of bug ? I mean bash took the liberty to ignore or incorrectly parse my starting quote

  • This error is from some bash script being run when you press tab (probably from bash-completion), not awk. What does running bash as bash -x say around the error? – Chris Down Jan 23 at 13:24
  • @ChrisDown Can you please explain a little bit about what bash -x does ? Then I can give you better information and also learn. – ng.newbie Jan 23 at 13:27
  • It outputs each thing which is being executed and will likely show the source of your problem. Once you get a prompt, try performing the repro steps again and look at what's immediately before this error. – Chris Down Jan 23 at 13:28
  • @ChrisDown I have edited the question to include the output of bash -x, it did include my awk script so I don't think this is entirely unrelated to awk. – ng.newbie Jan 23 at 13:33
  • @ChrisDown Wait, isn't this a bug? I mean in the last lines it says unquoted $t" but I do provide the full quotes and it does work. So isn't this some kind of bug ? I mean bash took the liberty to ignore or incorrectly parse my starting quote. – ng.newbie Jan 23 at 13:35
3

From your bash -x output, you have found a bug in the bash-completion package (which is not part of bash, but is a community-maintained package of tab completions). Your issue is the bash completion run in this case doesn't properly escape quoting when passing to eval:

+ printf -v quoted %s '$t" c'
+ [[ $t" c == \$* ]]
+ eval 'quoted=$t" c'
bash: unexpected EOF while looking for matching `"'
bash: syntax error: unexpected end of file

Looking at the bug tracker, this looks to be this bug, which has already been fixed upstream, but the patch hasn't made it into your repos yet.

You have a few options:

  1. Find a backport of bash-completion for your distribution. It's not mentioned what distribution that is in your question, but on Ubuntu for example, you may be able to find a new version in a PPA.
  2. Stop using the bash-completion package and just use bash's internal completion logic. Depending on what you need tab completion to do, this might be adequate.
  3. Wait it out for the fix to enter your distribution's repositories. Depending on your distribution the time it may take for the fix to make it there may vary from "in 5 minutes" to "never".
  4. If your distribution has a process around backporting upstream fixes, you may consider requesting a backport of the patch for this fix to be applied, instead of waiting for the new version. Depending on the maintainer and distribution's policy, this may or may not work.
| improve this answer | |
  • Good to know it really was a bug and not me just being a linux noob. – ng.newbie Jan 23 at 13:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.