我想知道是否可以多次匹配一个模式(匹配的数量不知道)并提取每个出现的数据进行比较?
我的目标是查找是否在接口上配置了vlan。
我有这个文件样本(我有截断它):
interface Ethernet1/16
shutdown
switchport access vlan 777
spanning-tree bpduguard enable
interface Ethernet1/17
switchport mode trunk
switchport trunk native vlan 201
switchport trunk allowed vlan 1-69,71-100,110-111,120,153,198,200-366,368-397,400-599,1000-3967,4048-4093
channel-group 2 mode active
interface Ethernet1/18
switchport mode trunk
switchport trunk native vlan 201
switchport trunk allowed vlan 1-69,71-100,110-111,120,153,198,200-366,368-397,400-599,1000-3967,4048-4093
channel-group 2 mode active
interface Ethernet1/19
switchport mode trunk
switchport trunk native vlan 201
switchport trunk allowed vlan 1-69,71-100,110-111,120,153,198,368-397,400-599,1000-3967,4048-4093
channel-group 2 mode active
我有这个代码用于解析文件和每个接口,我检查是否可以找到范围内的vlan(在参数中提供)。
REGEX="^interface (.*)"
REGEX_TRUNKRANGEVLAN="^switchport trunk allowed.*(\d+)-(\d+),*"
vlan=$2
while read line; do
if [[ $line =~ $REGEX ]]; then
ifname=${BASH_REMATCH[1]}
else
if [[ $line =~ $REGEX_TRUNKRANGEVLAN ]]; then
#for each pattern match on this line, I need to check
if [ ${BASH_REMATCH[1]} -lt $vlan ] && [ ${BASH_REMATCH[2]} -gt $vlan ]; then
echo "vlan is included in interface $ifname"
fi
fi
fi
done <$1
例如,如果我查找vlan 250,输出将为:
vlan包含在接口Ethernet1 / 17中 vlan包含在接口Ethernet1 / 18
中
答案 0 :(得分:1)
您需要提取所有范围并逐一进行测试。无需使用正则表达式模式提取它们,您可以使用IFS拆分行。凭借糟糕的bash功能:
$a=array(1,10,25,50);
rsort($a);
$number=15;
echo $number . " = ";
$final = [];
foreach($a as $num) {
if((int)($number / $num) > 0) {
$final = array_merge($final, array_fill(0, (int)($number / $num), $num));
$number -= (int)($number / $num) * $num;
}
}
echo implode(' + ', $final);
答案 1 :(得分:1)
我认为这会奏效:
REGEX="^interface (.*)"
REGEX_TRUNKRANGEVLAN="^[ ]*switchport trunk allowed vlan (.*)"
vlan=$2
while read line
do
if [[ $line =~ $REGEX ]]
then
ifname=${BASH_REMATCH[1]}
fi
if [[ $line =~ $REGEX_TRUNKRANGEVLAN ]]
then
old=$IFS
IFS=","
for range in ${BASH_REMATCH[1]}
do
if [[ $vlan -ge ${range%-*} && $vlan -le ${range#*-} ]]
then
echo "vlan is included in interface $ifname"
fi
done
IFS=$old
fi
done < $1
答案 2 :(得分:0)
我这样做了:
class Model_Search extends ORM
{
protected $_has_many = array(
'mp3s' => array(
'model' => 'Mp3',
'through' => 'searches_mp3s',
),
);
答案 3 :(得分:0)
显然不是最漂亮的方式,当然也不是最有效的方式,但因为我花了一些时间编写这个命令,即使问题解决了,我也会分享它:
sed -r -e ':a' -e 'N' -e '$!ba' -e 's/\n//g' -e 's/(interface Ethernet)/\n\1/g' |awk '{gsub(",", " ", $15); print "echo "$1"_"$2" "$15}' | sed -r 's#([0-9]*)-([0-9]*)#`seq \1 \2`#ge'
它的作用是将所有接口块转换为一行<interface> <ranges>
并转换vlan列表中每一行的所有范围。
即。如果该行是:<interface> 3-5 7 8-10
它将转变为:<interface> 3 4 5 7 8 9 10
-e ':a' -e 'N' -e '$!ba' -e 's/\n//g'
:删除所有\n
-e 's/(interface Ethernet)/\n\1/g'
:每个interface Ethernet
都将成为新行的开头awk '{gsub(",", " ", $15); print "echo "$1"_"$2" "$15}'
:将","
替换为" "
并打印interface Ethernet...
和范围字段。这里的诀窍是echo
将在下一个sed语句中使用 sed -r 's#([0-9]*)-([0-9]*)#
seq \ 1 \ 2 #ge'
:将vlan范围的每个模式XXX-XXX
替换为:seq XXX XXX
。然后e
标志将执行替换行。
将采用以下形式:
echo interface `seq 3 5` 7 `seq 8 10`
之后你只需要grep
出现vlan的行。
我认为现在对你没什么用处,但是我花了太多时间在这个上面分享它;)
- 编辑
一些awk脚本更加精致:
awk '/interface Ethernet[0-9]*\/[0-9]*/{iface=$1" "$2}; /switchport trunk allowed vlan/{ gsub(",", " "); print "echo "iface" \\" ; for(i = 5; i<=NF; i++) { if ($i~/[0-9]*-[0-9]*/) { gsub("-", " ", $i); printf (" `seq %s`", $i) } else { printf (" %s",$i) } ; if (i!=NF){print "\\"} else {print""} } }' /tmp/test.vlan | sh |grep ' 250 ' |cut -d" " -f1,2