-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparse
More file actions
executable file
·263 lines (233 loc) · 8.1 KB
/
parse
File metadata and controls
executable file
·263 lines (233 loc) · 8.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
#!/bin/bash
# Failed Tests and Issues:
#
# 1. **Test Input**: `parse --list "[1, 2, 3]" --nested '{"key": "value"}'`
# **Expected Output**:
# ```json
# {
# "args": {
# "count": 2,
# "input": "--list [1, 2, 3] --nested {\"key\": \"value\"}",
# "parsed": {
# "list": [1, 2, 3],
# "nested": {"key": "value"}
# }
# }
# }
# ```
# **Actual Behavior**:
# The parser fails because it does not properly handle JSON arrays and objects in the input.
# - The string `[1, 2, 3]` and `{"key": "value"}` are passed as plain strings to `jq` rather than being parsed as JSON objects and arrays.
# - This leads to errors when trying to treat the strings as valid JSON in the `jq` commands.
# - Specifically, the `jq` errors are related to interpreting the special characters `[` and `{`, causing it to fail with syntax errors related to `unexpected IDENT`.
#
# **Error Details**:
# ```bash
# jq: error: syntax error, unexpected IDENT, expecting end of file (Unix shell quoting issues?)
# jq: 1 compile error
# old_value_type is
# jq: error: $valarguments is not defined at <top-level>, line 1:
# .args.parsed.list = $valarguments
# jq: 1 compile error
# old_value_type is
# ```
#
# **Root Cause**:
# - When the string `"[1, 2, 3]"` and `'{"key": "value"}'` are passed to `jq`, they are treated as regular strings, not as valid JSON.
# - `jq` attempts to parse them as shell arguments, resulting in parsing errors and syntax errors.
# - There is also confusion with `$valarguments`, which indicates that some parts of the parser are trying to interpret values dynamically, but it is not handled correctly.
# - The key issue here is the parser's inability to recognize these inputs as JSON objects or arrays and pass them to `jq` accordingly.
#
# 2. **Test Input**: `parse --key$#@! "value"`
# **Expected Output**:
# ```json
# {
# "args": {
# "count": 2,
# "input": "--key$#@! value",
# "parsed": {
# "--key$#@!": "value"
# }
# }
# }
# ```
# **Actual Behavior**:
# - The parser fails to properly escape or handle keys that contain special characters like `$`, `#`, `@`, and `!`.
# - These characters interfere with how the shell and `jq` interpret the key, causing syntax errors when attempting to use them in the `jq` command.
# - The special characters cause `jq` to misinterpret the input, resulting in unexpected behavior or errors in the parsing process.
#
# **Error Details**:
# ```bash
# jq: error: syntax error, unexpected '-', expecting FORMAT or QQSTRING_START or '[' (Unix shell quoting issues?)
# jq: 1 compile error
# ```
#
# **Root Cause**:
# - Special characters in keys must be properly escaped when passed into `jq`.
# - The parser does not escape or handle special characters (`$`, `#`, `@`, `!`) in the key names, leading to issues in `jq` interpreting them.
# - Without escaping or quoting the key properly, `jq` interprets the special characters as part of its internal syntax, resulting in errors.
#
# 3. **Test Input**: `parse "some input with spaces" --flag --msg "hello world"`
# **Expected Output**:
# ```json
# {
# "args": {
# "count": 4,
# "input": "some input with spaces --flag --msg hello world",
# "parsed": {
# "unknown": "some input with spaces",
# "flag": true,
# "msg": "hello world"
# }
# }
# }
# ```
# **Actual Behavior**:
# - The parser works correctly for the most part but does not handle values with spaces inside quotes properly.
# - The string `"hello world"` is treated as two separate arguments: `"hello"` and `"world"`. This causes the parser to fail to interpret the entire quoted string as a single value.
#
# **Error Details**:
# ```bash
# jq: error: syntax error, unexpected IDENT, expecting end of file (Unix shell quoting issues?)
# ```
#
# **Root Cause**:
# - The parser needs to ensure that when an argument is enclosed in quotes (like `"hello world"`), it is treated as a single string with the space preserved.
# - The parser likely splits the arguments on spaces before checking if they are quoted, causing `"hello world"` to be incorrectly split into `"hello"` and `"world"`.
#
# **Summary**:
# - The parser fails to correctly handle:
# 1. JSON values like arrays and objects passed as strings.
# 2. Keys with special characters that are not properly escaped for `jq`.
# 3. Values inside quotes, especially when they contain spaces, which need to be handled as single arguments.
#
# These issues need to be addressed by ensuring proper escaping, handling of quoted strings, and proper parsing of JSON objects and arrays.
JSON='{}'
CURRENT_OPT=
BYPASS=0
# try not to mess with this structure, make other functions subfunctions of these below
main() {
initialize "$@"
parse "$@"
terminate
}
initialize() {
# count arguments and add to JSON
edit_json args.count $#
edit_json args.input "$*"
edit_json args.parsed '{}'
}
parse() {
# if start with --, add as key, else add as value, but if literal '--', then set -- = true
while [[ $# -gt 0 ]]; do
case "$1" in
# --) add_special_key '--' ;;
--help) print_help ;;
--*) add_key "$1" ;;
-*) add_key "-$1" ;;
*) add_value "$CURRENT_OPT" "$1" ;;
esac
shift
done
}
terminate() {
if [[ $BYPASS -ne 1 ]]; then
# output to stdout
jq . <<< "$JSON"
fi
}
get_json_type() {
query=".args.parsed.$1 | type"
result=$(echo "$JSON" | jq -r "$query")
echo "$result"
}
get_json_value() {
query=".args.parsed.$1"
result=$(echo "$JSON" | jq -r "$query")
echo "$result"
# # Return nothing if value is null, or "BOOL1" if it's true
# if [[ "$result" == "null" ]]; then
# return # This will return nothing
# elif [[ "$result" == "true" ]]; then
# echo "BOOL1" # Return BOOL1 if true
# elif [[ "$result" == "false" ]]; then
# echo "BOOL0" # Return BOOL0 if false
# else
# echo "$result" # Otherwise, just return the value
# fi
}
edit_json() {
local key="$1"
local val=$(trim "$2")
# Determine the type of the value
if [[ "$val" =~ ^[0-9]+$ ]]; then
# Number
JSON=$(echo "$JSON" | jq ".$key = $val")
elif [[ "$val" =~ ^\[(.*)\]$ ]]; then
# Array (must be in JSON format)
JSON=$(echo "$JSON" | jq --argjson val "$val" ".$key = \$val"arguments)
elif [[ "$val" =~ ^\{(.*)\}$ ]]; then
# JSON Object (must be in JSON format)
JSON=$(echo "$JSON" | jq --argjson val "$val" ".$key = \$val")
elif [[ "$val" == "true" || "$val" == "false" ]]; then
# Boolean
JSON=$(echo "$JSON" | jq ".$key = $val")
elif [[ "$val" == "null" ]]; then
# Null
JSON=$(echo "$JSON" | jq ".$key = null")
else
# String (default)
JSON=$(echo "$JSON" | jq ".$key = \"$val\"")
fi
}
reset_cache() {
CURRENT_OPT=
VALUES=
}
add_key() {
key= # the key to write to json file
reset_cache
# if key is literally --, set "--" to true
if [[ "$1" == '--' ]]; then
CURRENT_OPT='DOUBLEDASH'
else
CURRENT_OPT="${1:2}"
fi
edit_json "args.parsed.$CURRENT_OPT" true
}
add_value () {
key="$1"
new_value="$2"
# if key is empty, replace with 'unknown'
[[ -z "$key" ]] && key='unknown'
# get json value, modify, and write
old_value=$(get_json_value "$key")
old_value_type=$(get_json_type "$key")
# change datatype to (empty) string if boolean or null
case "$old_value_type" in
string) ;; # normal
boolean | null) old_value= ;;
*) >&2 echo "old_value_type is $old_value_type" ;;
esac
new_value=$(trim "$old_value $new_value")
# echo "old value is $old_value, type is $old_value_type, new value is $new_value" #debug
edit_json "args.parsed.$key" "$new_value"
}
# trim() {
# echo "$*" | xargs --null
# }
trim() {
echo "$*" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
}
print_help() {
BYPASS=1
echo "You have successfully bypassed this command. Sadly, nothing here."
}
main "$@"
# TEST CASES
# `none`
# string values
# --
# --key
# --key string value
# --key number