Linux脚本读取ini文件并按指定字符拆分为变量

Linux脚本读取ini文件并按指定字符拆分为变量,linux,Linux,我被困在以下任务中:让我们假设文件夹中有一个.ini文件。该文件包含如下行: eno1=10.0.0.254/24 eno2=172.16.4.129/25 eno3=192.168.2.1/25 tun0=10.10.10.1/32 我必须选择最大的子网掩码。所以我的尝试是: declare -A data for f in datadir/name do while read line do r=(${line//=/ }) let data[${r[0]}]=${r

我被困在以下任务中:让我们假设文件夹中有一个
.ini
文件。该文件包含如下行:

eno1=10.0.0.254/24 
eno2=172.16.4.129/25
eno3=192.168.2.1/25
tun0=10.10.10.1/32
我必须选择最大的子网掩码。所以我的尝试是:

declare -A data
for f in datadir/name

do
    while read line
    do
r=(${line//=/ })

let data[${r[0]}]=${r[1]}

    done < $f
done
declare-A数据
对于datadir/name中的f
做
读行时
做
r=(${line/=/})
让数据[${r[0]}]=${r[1]}
完成<$f
完成
这就是我走了多远。(是的,我知道名为name的文件不是
.ini
文件,而是
.txt
文件,因为我在创建ini文件时遇到了问题,所以这位老师甚至没有为我们的考试提供这样的文件。) 它将行拆分为=,但由于(第一个)的原因,它不想读取IP号。性格 (我收到的错误消息中的算术运算符无效)


如果有人能帮助我,并解释我如何为这样的任务制作脚本,我将非常感谢

不要使用
。这是算术课

$ help let
let: let arg [arg ...]
    Evaluate arithmetic expressions.

    Evaluate each ARG as an arithmetic expression.
只需使用直接赋值:

declare-A数据
对于datadir/name中的f
做
读行时
做
r=(${line/=/})
数据[${r[0]}]=${r[1]}
完成<$f
完成
结果:

$ declare -p data
declare -A data=([tun0]="10.10.10.1/32" [eno1]="10.0.0.254/24" [eno2]="172.16.4.129/25" [eno3]="192.168.2.1/25" )

不要使用
。这是算术课

$ help let
let: let arg [arg ...]
    Evaluate arithmetic expressions.

    Evaluate each ARG as an arithmetic expression.
只需使用直接赋值:

declare-A数据
对于datadir/name中的f
做
读行时
做
r=(${line/=/})
数据[${r[0]}]=${r[1]}
完成<$f
完成
结果:

$ declare -p data
declare -A data=([tun0]="10.10.10.1/32" [eno1]="10.0.0.254/24" [eno2]="172.16.4.129/25" [eno3]="192.168.2.1/25" )

awk
提供了一个简单的解决方案,用于查找
'/'
后面的最大值,该值将比bash脚本或Unix管道快几个数量级,使用:

awk -F"=|/" '$3 > max { max = $3 } END { print max }' file
示例使用/输出

$ awk -F"=|/" '$3 > max { max = $3 } END { print max }' file
32
上面的
awk
使用
'='
'/'
作为字段分隔符分隔字段,然后保持第三个字段
$3的最大值,并使用
结束{…}
规则输出该值

Bash解决方案

如果确实需要bash脚本解决方案,则可以使用
[[..=~]]
来隔离每行所需的部分,以填充
bash\u REMATCH
数组,然后将
${bash\u REMATCH[3]}
max
变量进行比较。带有
=~
[[…]]
表达式将右侧的所有内容视为扩展正则表达式,并将每个分组(
(…)
)隔离为数组
BASH_REMATCH
中的一个元素,例如

#!/bin/bash

[ -z "$1" ] && { printf "filename required\n" >&2; exit 1; }

declare -i max=0

while read -r line; do
    [[ $line =~ ^(.*)=(.*)/(.*)$ ]]
    ((${BASH_REMATCH[3]} > max)) && max=${BASH_REMATCH[3]}
done < "$1"

printf "max: %s\n" "$max"
(两个shell脚本解决方案的输出相同)


如果您还有其他问题,请与我联系。

awk
提供了一个简单的解决方案,用于查找
'/'
后面的最大值,该值将比bash脚本或Unix管道快几个数量级,使用:

awk -F"=|/" '$3 > max { max = $3 } END { print max }' file
示例使用/输出

$ awk -F"=|/" '$3 > max { max = $3 } END { print max }' file
32
上面的
awk
使用
'='
'/'
作为字段分隔符分隔字段,然后保持第三个字段
$3的最大值,并使用
结束{…}
规则输出该值

Bash解决方案

如果确实需要bash脚本解决方案,则可以使用
[[..=~]]
来隔离每行所需的部分,以填充
bash\u REMATCH
数组,然后将
${bash\u REMATCH[3]}
max
变量进行比较。带有
=~
[[…]]
表达式将右侧的所有内容视为扩展正则表达式,并将每个分组(
(…)
)隔离为数组
BASH_REMATCH
中的一个元素,例如

#!/bin/bash

[ -z "$1" ] && { printf "filename required\n" >&2; exit 1; }

declare -i max=0

while read -r line; do
    [[ $line =~ ^(.*)=(.*)/(.*)$ ]]
    ((${BASH_REMATCH[3]} > max)) && max=${BASH_REMATCH[3]}
done < "$1"

printf "max: %s\n" "$max"
(两个shell脚本解决方案的输出相同)


如果您还有其他问题,请告诉我。

前面介绍的两种解决方案都可以运行(并执行它们设计的功能);我想我应该在左栏添加一些东西,因为规格相当宽松

$ cat freasy 
eno1=10.0.0.254/24 
eno2=172.16.4.129/25
eno3=192.168.2.1/25
tun0=10.10.10.1/32
我认为最大的子网掩码是数值最低的子网掩码(容纳最多的主机)


之前提出的两种解决方案都可以运行(并实现其设计目标);我想我应该在左栏添加一些东西,因为规格相当宽松

$ cat freasy 
eno1=10.0.0.254/24 
eno2=172.16.4.129/25
eno3=192.168.2.1/25
tun0=10.10.10.1/32
我认为最大的子网掩码是数值最低的子网掩码(容纳最多的主机)


你如何比较IP号码?是什么使一个比另一个大?子网掩码是斜杠后面的部分。最大的子网掩码是斜杠后最大值的IP地址。如何比较IP号码?是什么使一个比另一个大?子网掩码是斜杠后面的部分。最大的子网掩码将是斜杠后具有最大值的IP地址。这似乎是
bash
编程分配,因此可能会排除实用程序。如果没有,可以使用
sort-t'/'-k2-r-ndatadir/name | head-1 | cut-d'/'-f2
`它被标记为
[linux]
,这样就可以覆盖linux实用程序,比如
sort
awk
。管道而不是单个进程的唯一缺点是为每个实用程序和管道生成子shell。对于效率显著不同的大型文件。这似乎是一个
bash
编程任务,因此可能会排除实用程序。如果没有,可以使用
sort-t'/'-k2-r-ndatadir/name | head-1 | cut-d'/'-f2
`它被标记为
[linux]
,这样就可以覆盖linux实用程序,比如
sort
awk
。管道而不是单个进程的唯一缺点是为每个实用程序和管道生成子shell。对于具有显著效率差异的大型文件。