awk提取键值对生成Shell脚本遇语法错误,求排查与解决方案
问题描述
现有文件中的一行内容如下:
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]
需要生成Shell脚本,针对方括号内的每一组xxx:yyy键值对,输出如下格式的命令行:
openscad --quiet --export-format binstl -D 'show=xxx' -o xxx.stl $1
注:原需求示例中的--quite是拼写错误,应为--quiet,且--export-format后缺少格式参数binstl,已做修正。
尝试了三段awk代码均触发语法错误,详情如下:
第一段代码
match($0, /\[[^\n\]]*\]$/) { # 提取[xx:yy, aa:bb]部分 s = substr($0, RSTART+1, RLENGTH-2); # 去掉首尾的[] n = split(s, arr,";"); # 拆分键值对 for(x in arr) { # 遍历每个键值对 match(arr[x], /([^\n:]+)/, b) { # 提取键值对的第一个字段 print subsgtr(b[1], RSTART, RLENGTH) } } }
报错信息:
gawk: prog:5: match(arr[x], /([^\n:]+)/, b) { # get the first field of the pair gawk: prog:5: ^ syntax error
第二段代码
match($0, /\[[^\n\]]*\]$/) { # 提取[xx:yy, aa:bb]部分 s = substr($0, RSTART+1, RLENGTH-2); # 去掉首尾的[] n = split(s, arr,";"); # 拆分键值对 for(x in arr) { # 遍历每个键值对 arr[x] ~ /([^\n:]+)/ print } }
报错信息:
gawk: prog:5: arr[x] ~ /([^\n:]+)/ print gawk: prog:5: ^ syntax error
第三段代码
match($0, /\[[^\n\]]*\]$/) { # 提取[xx:yy, aa:bb]部分 s = substr($0, RSTART+1, RLENGTH-2); # 去掉首尾的[] n = split(s, arr,";"); # 拆分键值对 for(x in arr) { # 遍历每个键值对 arr[x] ~ /([^\n:]+)/ { print } } }
报错信息:
gawk: prog:5: arr[x] ~ /([^\n:]+)/ { print } gawk: prog:5: ^ syntax error
需要解释上述错误原因,并给出能实现需求的正确方案。
错误原因解析
第一段代码错误
- match函数语法违规:awk中
match()是函数调用,不能直接后跟代码块{},需先执行匹配,再通过if判断结果或直接使用匹配后的内置变量。 - 拼写错误:
subsgtr是substr的笔误。 - 分隔符错误:拆分键值对应该用逗号
,,而非分号;。
第二段代码错误
awk的条件判断后必须用{}包裹执行语句,或显式添加if关键字,直接写条件 print不符合语法规范。
第三段代码错误
用~做正则匹配时,不能直接将条件与代码块连写,必须加上if关键字,正确写法应为if (arr[x] ~ /([^\n:]+)/) { print }。
正确实现方案
以下awk脚本可完成需求,同时修正了原openscad命令的参数顺序错误:
# 匹配行尾方括号内的内容,捕获到m[1]中 match($0, /\[([^\]]+)\]$/, m) { # 拆分键值对,自动处理逗号前后的空格 n = split(m[1], pairs, /,\s*/) # 遍历所有键值对(用索引遍历保证顺序) for (i=1; i<=n; i++) { # 拆分键和值 split(pairs[i], kv, /:/) # 去除键名前后的空格(适配带空格的键名如wall mount) gsub(/^\s+|\s+$/, "", kv[1]) # 生成目标命令行 printf "openscad --quiet --export-format binstl -D 'show=%s' -o %s.stl \$1\n", kv[1], kv[1] } }
使用步骤
- 将上述代码保存为
gen_scad_cmds.awk - 执行命令生成Shell脚本:
awk -f gen_scad_cmds.awk 你的输入文件名 > generate_stl.sh chmod +x generate_stl.sh
- 运行生成的脚本:
./generate_stl.sh 你的openscad源文件.scad
关键说明
- 用
match()的第三个参数直接捕获方括号内的内容,避免手动截取字符串的繁琐操作 - 拆分键值对时使用
/,\s*/正则,自动处理逗号后的空格 - 用
gsub()清理键名前后的空格,适配带空格的键名 - 修正了原openscad命令的参数顺序:
--export-format后必须跟格式参数binstl,调整-D参数到正确位置,同时修正了--quite的拼写错误
内容的提问来源于stack exchange,提问作者MyTallest
相关产品推荐
相关产品推荐

