我有一些输出需要解析成如下所示的数组。条目数可以改变。
interface : eth1
ip address : 1.1.1.1 [Active]
subnet mask: 255.255.255.0
router : 1.1.1.2
name server: 1.1.1.3
dhcp server: 1.1.1.4
lease time : 86400
last update: Fri Jul 5 00:11:12 UTC 2013
expiry : Sat Jul 06 00:11:08 UTC 2013
reason : BOUND
interface : eth2
ip address : 2.2.2.2 [Active]
subnet mask: 255.255.255.0
router : 2.2.2.3
name server: 2.2.2.4
dhcp server: 2.2.2.5
lease time : 86400
last update: Fri Jul 5 03:03:41 UTC 2013
expiry : Sat Jul 06 03:03:39 UTC 2013
reason : REBOOT
每个部分以界面开头,以理由结束,理由后以空白行结束。
我很擅长bash脚本编写,并且已经尝试了我能想到的所有内容,以便将每个部分变成一个变量,而我似乎无法让它工作。如果这是任何其他语言......我可以在心跳中做到这一点!
基本上我想要的是一个数组,其中每个部分都包含其间的所有细节(这些细节也可以改变,而不是有多少行)。
我用awk,sed,grep等尝试了许多不同的方法......它们似乎都没有让我到达我想要的位置。
最终应该是什么样的:
$output_array[$1]=
interface : eth1
ip address : 1.1.1.1 [Active]
subnet mask: 255.255.255.0
router : 1.1.1.2
name server: 1.1.1.3
dhcp server: 1.1.1.4
lease time : 86400
last update: Fri Jul 5 00:11:12 UTC 2013
expiry : Sat Jul 06 00:11:08 UTC 2013
reason : BOUND
$output_array[$2]=
interface : eth1
ip address : 1.1.1.1 [Active]
subnet mask: 255.255.255.0
router : 1.1.1.2
name server: 1.1.1.3
dhcp server: 1.1.1.4
lease time : 86400
last update: Fri Jul 5 00:11:12 UTC 2013
expiry : Sat Jul 06 00:11:08 UTC 2013
reason : BOUND
有人能指出我正确的方向吗?谢谢!
我尝试过的一个例子,信息没有拆分,或者我做错了什么!
output_array=echo $output | awk -v x="^$" -v n=1 '$0 ~ x {n++; next}{print}'
for items in $output_array; do
echo "ENTRY: $items"
done
答案 0 :(得分:1)
一种脏方式:
$ cnt=$(gawk -v RS='\n\n' 'END{print NR}' file)
$ for ((i=1;i<=cnt;i++)); do
a+=("$(gawk -v l="$i" -v RS='\n\n' 'NR==l' file)");
done
$ echo "${a[0]}"
interface : eth1
ip address : 1.1.1.1 [Active]
subnet mask: 255.255.255.0
router : 1.1.1.2
name server: 1.1.1.3
dhcp server: 1.1.1.4
lease time : 86400
last update: Fri Jul 5 00:11:12 UTC 2013
expiry : Sat Jul 06 00:11:08 UTC 2013
reason : BOUND
$ echo "${a[1]}"
interface : eth2
ip address : 2.2.2.2 [Active]
subnet mask: 255.255.255.0
router : 2.2.2.3
name server: 2.2.2.4
dhcp server: 2.2.2.5
lease time : 86400
last update: Fri Jul 5 03:03:41 UTC 2013
expiry : Sat Jul 06 03:03:39 UTC 2013
reason : REBOOT
答案 1 :(得分:1)
这是你的黑客攻击:
IFS=$'\x01'
output_array=($(cat someoutput | sed -e "s/^$/$IFS/"))
IFS=$' \t\n'
它将bash设置为由不可打印的字符拆分,然后在所有空行上插入该不可打印的字符。然后它将IFS设置回其默认值,因此它不会干扰脚本的其余部分。
答案 2 :(得分:0)
我使用了@that其他人的建议和更多的研究
有人可以改进吗?
output+=$'\n'
x=0
while read -r line
do
if [ -z "$line" ]; then
output_array[$x]=$data
unset data
let x++
else
data+=$'\n'
data+=$line
fi
done <<< "$output"
for j in "${output_array[@]}"
do
echo "$j"
done
答案 3 :(得分:0)
@jivetek - 这并不是对你所写内容的改进,但令我感到困扰的是,我无法根据@thatotherguy发布的解决方案获得解决方案,正如我所期望的那样。这是一个使用两个不可打印的字符的版本,以及一些我不明白的bash魔法。需要注意的是,“\ 002”字符留在数组元素中。它需要第二次通过数组来清理每个元素,但这可能很容易在你的脚本中的其他地方做(可能你需要走这些数据)
IFS=$'\001'
IN=`awk '/^$/ {print "\001"} { print $0 "\002" }' input`
IFS=$'\001\n' read -a oarr3 -d$IFS <<< $IN
IFS=$' \t\n'
其中input只是您在“input”文件中的数据。
从this so question找到“读取”命令。我不明白的“魔法”是为什么IFS的双重赋值与“-d”标志一起工作时,我认为我不需要像它们那样的东西。
oarr3的内容是我所期望的(主要是):
declare -a oarr3='([0]="interface : eth1 ip address : 1.1.1.1 [Active] subnet mask: 255.255.255.0 router : 1.1.1.2 name server: 1.1.1.3 dhcp server: 1.1.1.4 lease time : 86400 last update: Fri Jul 5 00:11:12 UTC 2013 expiry : Sat Jul 06 00:11:08 UTC 2013 reason : BOUND " [1]=" interface : eth2 ip address : 2.2.2.2 [Active] subnet mask: 255.255.255.0 router : 2.2.2.3 name server: 2.2.2.4 dhcp server: 2.2.2.5 lease time : 86400 last update: Fri Jul 5 03:03:41 UTC 2013 expiry : Sat Jul 06 03:03:39 UTC 2013 reason : REBOOT")'
但是,就像我说的那样,“\ 002”字符仍然存在于每个数组元素中,并且“\ 002”字符后面还可能有一个空格:
echo "${oarr3[0]}" | tr '\002' '\n'
interface : eth1
ip address : 1.1.1.1 [Active]
subnet mask: 255.255.255.0
router : 1.1.1.2
name server: 1.1.1.3
dhcp server: 1.1.1.4
lease time : 86400
last update: Fri Jul 5 00:11:12 UTC 2013
expiry : Sat Jul 06 00:11:08 UTC 2013
reason : BOUND
[0]
这里是原始数据的视图:
cat -etv <<< ${oarr3[0]} interface : eth1^B ip address : 1.1.1.1 [Active]^B subnet mask: 255.255.255.0^B router : 1.1.1.2^B name server: 1.1.1.3^B dhcp server: 1.1.1.4^B lease time : 86400^B last update: Fri Jul 5 00:11:12 UTC 2013^B expiry : Sat Jul 06 00:11:08 UTC 2013^B reason : BOUND^B $
同样看起来第二个元素中有一个领先的“\ 002”。这可能是因为我不得不从awk输出中返回并将它们包含在第二个IFS声明中。当需要处理数据时,可以通过重新唤醒来解决这个问题。
Shell版本:
sh -version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.