Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash-解析ini文件,通过中的值查找节名_Bash_Awk_Sed_Grep_Ini - Fatal编程技术网

Bash-解析ini文件,通过中的值查找节名

Bash-解析ini文件,通过中的值查找节名,bash,awk,sed,grep,ini,Bash,Awk,Sed,Grep,Ini,我有一个config.ini文件,看起来像这样(已更新): 我需要获得房间号,其中3个给定值(base,hwadd,lock)与脚本参数匹配。假设bash脚本的调用方式如下: script.sh 100 0x20 105 脚本将返回4(因为所有3个参数都匹配group4) 找到一个单一的价值是小菜一碟 source config.ini 每个值都在$valX下可用,但这并不是解析节名,因此在这种情况下它是无用的。请尝试以下内容,它是以shell脚本的形式运行的,用户需要为脚本提供参数(使用显

我有一个config.ini文件,看起来像这样(已更新):

我需要获得房间号,其中3个给定值(basehwaddlock)与脚本参数匹配。假设bash脚本的调用方式如下:

script.sh 100 0x20 105
脚本将返回4(因为所有3个参数都匹配group4)

找到一个单一的价值是小菜一碟

source config.ini

每个值都在$valX下可用,但这并不是解析节名,因此在这种情况下它是无用的。

请尝试以下内容,它是以shell脚本的形式运行的,用户需要为脚本提供参数(使用显示的示例进行测试和编写)



解释:在此处添加上述代码的详细解释

cat script.ksh
val="$@"                         ##Creating a shell variable named val which has all values of arguments passed to script.
awk -v arg="$val" '              ##Starting an awk program from here and creating a variable arg whose value is shell variable val here.
BEGIN{                           ##Starting BEGIN section from here.
  FS="="                         ##Setting FS as = here.
  num=split(arg,array," ")       ##Splitting arg variable into an array with delimiter as space here.
  for(i=1;i<=num;i++){           ##Running for loop from i=1 to till value of num here.
    array1[array[i]]             ##Creating an array named array1 with index of value of array with index i here.
  }
}
/group/{                         ##Checking condition if line contains group string then do following.
  if(sum==num){                  ##Checking condition if sum==num then do following.
    print group_value            ##Printing variable group_value here.
  }
  sum=""                         ##Nullifying variable sum here.
  gsub(/[^0-9]*/,"")             ##Globally substituting everything apart from digits with NULL here in current line.
  group_value=$0                 ##Setting variable group_value value to current line value here.
  next                           ##next will skip all further statements from here.
}
($NF in array1){                 ##Checking condition if last field of current line is present in array1 then do following.
  sum++                          ##Increase count of sum variable with 1 here.
}
END{                             ##Starting END block for this code here.
  if(sum==num){                  ##Checking condition if sum==num then do following.
    print group_value            ##Printing variable group_value here.
  }
}
'  Input_file                    ##Mentioning Input_file name here.
cat script.ksh
val=“$@”##创建一个名为val的shell变量,该变量具有传递给脚本的所有参数值。
awk-v arg=“$val””##从此处启动awk程序并在此处创建值为shell变量val的变量arg。
开始{##从这里开始开始开始部分。
FS=“=”##将FS设置为=此处。
num=split(arg,array,“”)##将arg变量拆分为一个数组,其中分隔符作为空格。
对于(i=1;i您可以使用此awk:

val='100 0x20 105'

awk -F= -v vals="$val" 'BEGIN {
   n = split(vals, w, /[ \t]+/)
   for (i=1; i<=n; i++)
      values[w[i]] = 1
}
/^\[group[0-9]+]$/ {
   if (n == found)
      print grp
   delete seen
   found = 0
   grp = $0
   gsub(/^\[group|\]$/, "", grp)
}
NF == 2 && values[$2] && !seen[$2]++ {
   found++
}
END {
   if (n == found)
      print grp
}' file

您的脚本
script.sh
可能是:

#!/bin/bash

sed '/^\[/p;/^base/p;/^hwadd/p;/^lock/p;d' config.ini |   # keep relevant lines
awk '
  BEGIN{RS = "["; FS = "\n"}
  {print $1, $2, $3, $4}
' |                                   # awk puts each block on one line
grep "base=$1 hwadd=$2 lock=$3" |     # filter line matching all records
sed -e 's/^group//' -e 's/\].*$//'    # extract group # from matching line
如果您发出带有上述更新的
config.ini
文件的
/script.sh 100 0x20 105
,则输出将为:

4
config.ini
中,条目
base=…
hwaddr=…
lock=…
必须始终按此顺序出现以进行匹配。如果不是这样,请让我调整脚本。

#!/bin/bash
val1=$1 # get value1
val2=$2 # get value2
val3=$3 # get value3
file="config.ini"   # ini file
raw=$(cat "$file")  # read file to this var
raw=${raw//$'\n'/ } # change new line to space
raw=${raw//[/'\n'}  # change [ to new line
# print through sed, sed prints number of group in matched string
printf "$raw" | sed -n "s/group\([0-9]*\).*$val1.*$val2.*$val3.*/\1/p"
用法


只要输入数据有名称-值对,最好先创建一个数组(
f[]
如下)这将这些名称映射到它们的值,然后在每个记录的末尾,您可以简单地按名称以您喜欢的任何组合比较这些值,并按您喜欢的任何顺序打印您喜欢的任何值,只需按名称引用它们即可

$ cat tst.awk
BEGIN { FS=" *= *"; OFS="=" }
NF {
    if ( /]/ ) {
        gsub(/[^0-9]/,"")
        f["group"] = $0
    }
    else {
        f[$1] = $2
    }
    next
}
{ prt() }
END { prt() }

function prt() {
    if ( (f["base"] == base) && (f["hwadd"] == hwadd) && (f["lock"] == lock) ) {
        print f["group"]
    }
    delete f
}

$ awk -v base=100 -v hwadd=0x20 -v lock=105 -f tst.awk file
4


这三个似乎都与第二组匹配。你试过什么吗?告诉我们!!我以前没有看到techno的评论,发布了我的解决方案,我现在已经删除了它;一旦你在你的问题中添加了你的努力,那么将取消删除我的答案。tbh。我不知道如何开始,我知道正则表达式,以及如何在一行内找到字符串,但这远远超出了我的理解范围我的第一种方法是“source config.ini”,但这不是解析部分names@trojan编写一个脚本,从给定的示例输入中生成预期的输出总是相对简单的,但要想不为其他输入生成意外的输出则要困难得多您必须真正理解代码(如果不理解,请提问)和/或拥有一个包含所有边缘/雨天案例的输入集。仅仅看到它从您发布的示例输入中产生预期输出几乎不足以判断答案是否“有效”或者不是。谢谢您提供的非常详细的答案!当我在实时数据上测试时,我得到了不止一个节号,我用真实数据更新了我的问题。@特洛伊木马,我用您第一次显示的示例测试了这个问题,它对我很有效。我不确定“获得不止一个节”是什么意思请您详细说明一下,请使用更新的示例并尝试使用100 0x21 102作为输入参数-您的脚本将返回“2 8”但是应该只返回8I'm Get error:在第8行和第18行:对array rI的非法引用包含了一个与您的更新数据相关的工作演示链接。请告诉我这是否有效。这与要求不符。是的,它将根据发布的示例输入生成预期的输出,但这只是识别solu的起点操作,而不是结束点。例如,尝试将记录4中的
base=100…lock=105更改为
base=105…lock=100
,脚本仍会输出
4
,尽管您希望找到一个以base 100和lock 105为基础的记录。您可以将其完全更改为
base=7 lock=3 bookingnr=105 kode=100
,并且仍然可以获得
4
output。谢谢Ed。当问题被框起来时,我发布了答案,因为我可以再次调整答案,但在得到答案后改变问题的性质不是一个好的做法。当您使用awk时,您永远不需要sed或grep。也许@Ed Morton是对的,但您的代码确实有效!@特洛伊木马代码为给定的inp生成预期输出UT SET是识别一个解决方案的起点,而不是终点。除此之外,你还必须考虑软件中所有重要的东西——清晰度、性能、可靠性、健壮性、可维护性、易用性等等。awk的行数?我更喜欢使用每个工具来设计它。顺便问一下,在awk中使用函数gsub不是对sed或grep的隐藏调用吗?wrt
为什么
-因为将软件中最重要的东西(清晰性、性能、可靠性、健壮性、可维护性)结合起来,结果会更好可扩展性、易增强性等。你不需要为这个问题编写15行awk,你可以用一个更简单的脚本来解决它,但简洁性不是软件的目标,因此如果你不关注它,你就会得到一个更好的解决方案。wrt
gsub()
-这就像在问
sed和grep的使用不是对ed的隐藏调用吗?
并且它有相同的答案,它的类似功能和丝毫不隐藏您的脚本没有考虑配置文件中可能具有与p相同值的其他变量
#!/bin/bash

sed '/^\[/p;/^base/p;/^hwadd/p;/^lock/p;d' config.ini |   # keep relevant lines
awk '
  BEGIN{RS = "["; FS = "\n"}
  {print $1, $2, $3, $4}
' |                                   # awk puts each block on one line
grep "base=$1 hwadd=$2 lock=$3" |     # filter line matching all records
sed -e 's/^group//' -e 's/\].*$//'    # extract group # from matching line
4
#!/bin/bash
val1=$1 # get value1
val2=$2 # get value2
val3=$3 # get value3
file="config.ini"   # ini file
raw=$(cat "$file")  # read file to this var
raw=${raw//$'\n'/ } # change new line to space
raw=${raw//[/'\n'}  # change [ to new line
# print through sed, sed prints number of group in matched string
printf "$raw" | sed -n "s/group\([0-9]*\).*$val1.*$val2.*$val3.*/\1/p"
$ ./test xyz xyy zyx
4
$ cat tst.awk
BEGIN { FS=" *= *"; OFS="=" }
NF {
    if ( /]/ ) {
        gsub(/[^0-9]/,"")
        f["group"] = $0
    }
    else {
        f[$1] = $2
    }
    next
}
{ prt() }
END { prt() }

function prt() {
    if ( (f["base"] == base) && (f["hwadd"] == hwadd) && (f["lock"] == lock) ) {
        print f["group"]
    }
    delete f
}

$ awk -v base=100 -v hwadd=0x20 -v lock=105 -f tst.awk file
4