首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有一种方法可以读取由制表符分隔的键值对?

是否有一种方法可以读取由制表符分隔的键值对?
EN

Stack Overflow用户
提问于 2019-06-17 12:37:44
回答 1查看 159关注 0票数 0

我正在编写一个基于配置文件的构建环境,但是在解析它们时遇到了困难。该环境包含Makefiles (bmake),它们试图读取相应设置CFLAGS的配置。

配置文件保持简单,不需要特殊的=签名:

代码语言:javascript
复制
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.

我无法找到用grepsedawk解析这些选项的正确正则表达式。因为我很想在简单的conditional statements中通过bmake来确定这些特性。

代码语言:javascript
复制
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 )?我想过要打招呼这个文件或者用awk.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-17 13:09:11

将配置文件读入关联数组:

代码语言:javascript
复制
$ 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"]}是否已被填充。

或者,如果你想选择的话:

代码语言:javascript
复制
$ 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

您喜欢哪种语法:

代码语言:javascript
复制
$ 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)作为“字段”对待所必需的):

代码语言:javascript
复制
$ 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

最后更新:所有考虑过的事情--这可能是您真正想要的:

代码语言:javascript
复制
$ 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)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56631477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档