shell - 有没有办法读取由制表符分隔的键值对?
问题描述
我正在编写基于配置文件的构建环境,但在解析它们时遇到了困难。该环境包含尝试读取配置以进行相应设置的 Makefile (bmake) CFLAGS
。
配置文件保持简单,不需要特殊=
符号:
ident Appname # E.g. core.S:15: .ident $ident$
cpu arch (amd64, x86) # -march=cpuarch -mtune=cpuarch
option debug # Enable debugging.
option sanitize # Sanitize undefined behaviour.
option asyncio # Asynchronous I/O.
option ccpipe # GCC/Clang -pipe option.
我无法找出正确的正则表达式来使用 , 或 解析grep
这些sed
选项awk
。因为我很想用简单conditional statements
的方式确定这些特征bmake
,例如
DBG_ENABLED!= $read if option debug is set$ ? yes : no.
.if ${DBG_ENABLED} != ""} || ${DBG_ENABLED} == "yes" || ${DBG_ENABLED} != "no"
CFLAGS+= -O -g
.else
CFLAGS+= -O2
.endif
PIPE_ENABLED!= $read if option ccpipe is set$ ? yes : no.
.if ${PIPE_ENABLED} != "no"
CFLAGS+= -pipe
.endif
那么如何通过shell命令确定设置了X
例如选项option debug
?我考虑过 grepping 文件或使用awk
...
解决方案
将配置文件读入关联数组:
$ declare -A opts="( $(awk -F'\t+' 'NF{print "["$1","$2"]=1"}' file) )"
$ for idx in "${!opts[@]}"; do echo "$idx=${opts[$idx]}"; done
cpu,arch (amd64, x86)=1
option,debug=1
option,asyncio=1
option,ccpipe=1
option,sanitize=1
ident,Appname=1
然后只是测试${opts["option,debug"]}
是否被填充。
或者,如果您更愿意获得以下选项:
$ declare -A opts="( $(awk -F'\t+' '$1=="option"{print "["$2"]=1"}' file) )"
$ for idx in "${!opts[@]}"; do echo "$idx=${opts[$idx]}"; done
ccpipe=1
sanitize=1
asyncio=1
debug=1
无论您喜欢哪种语法:
$ if (( ${opts[debug]} )); then echo "do debug stuff"; else echo "nope, dont do it"; fi
do debug stuff
$ if (( ${opts[fluff]} )); then echo "do debug stuff"; else echo "nope, dont do it"; fi
nope, dont do it
$ if [[ -n ${opts[debug]} ]]; then echo "do debug stuff"; else echo "nope, dont do it"; fi
do debug stuff
$ if [[ -n ${opts[fluff]} ]]; then echo "do debug stuff"; else echo "nope, dont do it"; fi
nope, dont do it
更新:由于您的文件显然没有像您所说的那样真正以制表符分隔,因此删除注释然后删除所有剩余的前导/尾随空格并使用第一个剩余的空白链作为第一个字段和其余部分之间的分隔符该行(必须arch (amd64, x86)
在第一个脚本中视为“字段”):
$ declare -A opts="( $(awk '{sub(/#.*/,""); gsub(/^[[:space:]]+|[[:space:]]+$/,"")} NF{k=$1; sub(/[^[:space:]]+[[:space:]]+/,""); print "["k","$0"]=1"}' file) )"
$ for idx in "${!opts[@]}"; do echo "$idx=${opts[$idx]}"; done
cpu,arch (amd64, x86)=1
option,debug=1
option,asyncio=1
option,ccpipe=1
option,sanitize=1
ident,Appname=1
$ declare -A opts="( $(awk '{sub(/#.*/,""); gsub(/^[[:space:]]+|[[:space:]]+$/,"")} $1=="option"{print "["$2"]=1"}' file) )"
$ for idx in "${!opts[@]}"; do echo "$idx=${opts[$idx]}"; done
ccpipe=1
sanitize=1
asyncio=1
debug=1
最后更新:所有事情都认为这可能是你真正想要的:
$ declare -A opts="( $(awk '
{
sub(/#.*/,"")
gsub(/^[[:space:]]+|[[:space:]]+$/,"")
}
NF && ($1 != "ident") {
f1 = $1
sub(/[^[:space:]]+[[:space:]]+/,"")
f2 = $0
if (f1 == "option") {
idx = f2
val = 1
} else {
idx = f1
val = f2
}
print "[" idx "]=\"" val "\""
}
' file ) )"
$ for idx in "${!opts[@]}"; do echo "$idx=${opts[$idx]}"; done
ccpipe=1
sanitize=1
asyncio=1
debug=1
cpu=arch (amd64, x86)
推荐阅读
- python - psycopg2.errors.StringDataRightTruncation:对于类型字符变化的值太长(256)
- c# - C# AES 加密行为奇怪
- android - 活动包缺少附加功能,即使它们应始终添加到 newIntance 方法中
- javascript - Use google's autocomplete service to search (and output) only country and/or city
- python - 在 django 中使用 mongodb 时我应该运行 makemigrations 并迁移吗?
- mysql - Mysql:根据“关键字”位置搜索数据库
- python-3.x - sqlite3 无法打开数据库
- testing - Kotlin 测试 DSL 中的限制
- python - Jupyter notebook 错误 ModuleNotFoundError: No module named 'datascience'
- mysql - 如何将多个查询组合到同一个表但不同的列中?