query.awk (3021B)
1 #!/bin/awk -f 2 BEGIN { 3 in_string = 0 4 } 5 6 function out(str) { 7 if(length(str)) { 8 printf "%s", str 9 last_out = str 10 } 11 } 12 13 # called for expanding {< >} 14 # global variable expand_remaining used as input 15 function expand_query( expanded) { 16 if(DEBUG) printf "E: →%s←\n", expand_remaining >"/dev/stderr" 17 expanded = "" 18 while(match(expand_remaining, "['<>]")) { 19 if(RSTART > 1) { 20 expanded = expanded "\"" substr(expand_remaining, 1, RSTART-1) "\"" 21 if(DEBUG) printf "e: →%s←\n", expanded >"/dev/stderr" 22 } 23 char = substr(expand_remaining, RSTART, 1) 24 expand_remaining = substr(expand_remaining, RSTART+1) 25 if(char == ">") 26 return "get("expanded")" 27 else if(char == "<") { 28 expanded = expanded expand_query() 29 if(DEBUG) printf "e: →%s←\n", expanded >"/dev/stderr" 30 } else if(char == "'") { 31 if(match(expand_remaining, "'")) { 32 expanded = expanded "(" substr(expand_remaining, 1, RSTART-1) ")" 33 if(DEBUG) printf "e: →%s←\n", expanded >"/dev/stderr" 34 expand_remaining = substr(expand_remaining, RSTART+1) 35 } else { 36 expanded = expanded "(" expand_remaining ")" 37 if(DEBUG) printf "e: →%s←\n", expanded >"/dev/stderr" 38 expand_remaining = "" 39 } 40 } else { 41 print "ERROR: internal error in expand_query()" >"/dev/stderr" 42 exit 1 43 } 44 } 45 if(expand_remaining) { 46 expanded = expanded "\"" expand_remaining "\"" 47 if(DEBUG) printf "e: →%s←\n", expanded >"/dev/stderr" 48 expand_remaining = "" 49 } 50 return "get("expanded")" 51 } 52 53 function parse_line(line) { 54 while(length(line)) { 55 if(DEBUG) printf "%d: →%s←\n", in_string, line >"/dev/stderr" 56 if(in_string) { 57 if(match(line, /^(\\.|[^"\\])+/)) { 58 out(substr(line, 1, RLENGTH)) 59 line = substr(line, RLENGTH+1) 60 } 61 if(match(line, /^"/)) { 62 out("\"") 63 line = substr(line, 2) 64 in_string = 0 65 } else if(match(line, /^\\$/)) { 66 out("\\") 67 line = "" 68 } else if(!line) { 69 # is this valid? 70 } else { 71 print "string parsing error" >"/dev/stderr" 72 if(DEBUG) printf "%d: →%s←\n", in_string, line >"/dev/stderr" 73 exit 1 74 } 75 } else if(match(line, /^#/)) { 76 out(line) 77 line = "" 78 } else if(match(line, /[<"]/)) { 79 out(substr(line, 1, RSTART-1)) 80 line = substr(line, RSTART) 81 if(match(line, /^"/)) { 82 line = substr(line, 2) 83 in_string = 1 84 out("\"") 85 } else { 86 if(DEBUG) printf "q: →%s← →%s←\n", last_out, line >"/dev/stderr" 87 if( \ 88 match(last_out, /[[( \n\t]$/) && \ 89 match(line, /^<([a-zA-Z0-9._<>]|'[^']*')*>/) \ 90 ) { 91 expand_remaining = substr(line, 2, RLENGTH-2) 92 line = substr(line, RLENGTH+1) 93 out(expand_query()) 94 } else if(match(line, /^<[^<"]*/)) { 95 if(DEBUG) printf("SKIP: →%s← →%s← →%s←\n", last_out, \ 96 substr(line, 1, RLENGTH), substr(line, RLENGTH+1) \ 97 ) >"/dev/stderr" 98 out(substr(line, 1, RLENGTH)) 99 line = substr(line, RLENGTH+1) 100 } else { 101 out(line) 102 line = "" 103 } 104 } 105 } else { 106 out(line) 107 line = "" 108 } 109 } 110 out("\n") 111 } 112 113 { parse_line($0) }