如何根据上下文拆分文件?

如何根据上下文拆分文件?

lldpneighbors我有一些文件包含来自我们所有服务器的命令结果。我想将这些文件拆分为每个服务器的单独文件,以便更轻松地将这些数据导入到我们的库存系统中。

示例输入

=== Output from 00000000-0000-0000-0000-000000000000 (SERVERNAME1):
Interface 'ixgbe0' has 1 LLDP Neighbors: 
Neighbor 1:
    Chassis ID:         MAC Address - 00 01 02 03 04 05 
    Port ID:        Interface Name - TenGigabitEthernet 0/6
    Time To Live:       120 seconds
    System Name:        name-of-switch-01
    End Of LLDPDU:  
Interface 'igb0' has 1 LLDP Neighbors: 
Neighbor 1:
    Chassis ID:         MAC Address - 00 01 02 03 04 05 
    Port ID:        Interface Name - TenGigabitEthernet 0/23
    Time To Live:       120 seconds
    System Name:        name-of-switch-02
    End Of LLDPDU:  
=== Output from 00000000-0000-0000-0000-000000000000 (SERVERNAME2):
Interface 'ixgbe0' has 1 LLDP Neighbors: 
Neighbor 1:
    Chassis ID:         MAC Address - 00 01 02 03 04 05 
    Port ID:        Interface Name - TenGigabitEthernet 0/2
    Time To Live:       120 seconds
    System Name:        name-of-switch-01
    End Of LLDPDU:  
Interface 'igb0' has 1 LLDP Neighbors: 
Neighbor 1:
    Chassis ID:         MAC Address - 00 01 02 03 04 05 
    Port ID:        Interface Name - TenGigabitEthernet 0/19
    Time To Live:       120 seconds
    System Name:        name-of-switch-02
    End Of LLDPDU: 

这大致就是所有结果的样子,但有一些变化(它们的长度并不相同,有些由于接口较多而长了几行)。我想要匹配的分隔字符串是:

=== Output from [UUID] ([HOSTNAME]):

理想情况下,我希望每个文件都被命名为主机名(这只是为了方便,并不是必需的),因此上面的结果将被分成如下文件:

服务器名称1

=== Output from 00000000-0000-0000-0000-000000000000 (SERVERNAME1):
Interface 'ixgbe0' has 1 LLDP Neighbors: 
Neighbor 1:
    Chassis ID:         MAC Address - 00 01 02 03 04 05 
    Port ID:        Interface Name - TenGigabitEthernet 0/6
    Time To Live:       120 seconds
    System Name:        name-of-switch-01
    End Of LLDPDU:  
Interface 'igb0' has 1 LLDP Neighbors: 
Neighbor 1:
    Chassis ID:         MAC Address - 00 01 02 03 04 05 
    Port ID:        Interface Name - TenGigabitEthernet 0/23
    Time To Live:       120 seconds
    System Name:        name-of-switch-02
    End Of LLDPDU: 

服务器名称2

=== Output from 00000000-0000-0000-0000-000000000000 (SERVERNAME2):
Interface 'ixgbe0' has 1 LLDP Neighbors: 
Neighbor 1:
    Chassis ID:         MAC Address - 00 01 02 03 04 05 
    Port ID:        Interface Name - TenGigabitEthernet 0/2
    Time To Live:       120 seconds
    System Name:        name-of-switch-01
    End Of LLDPDU:  
Interface 'igb0' has 1 LLDP Neighbors: 
Neighbor 1:
    Chassis ID:         MAC Address - 00 01 02 03 04 05 
    Port ID:        Interface Name - TenGigabitEthernet 0/19
    Time To Live:       120 seconds
    System Name:        name-of-switch-02
    End Of LLDPDU: 

我正在尝试用来csplit完成此任务,但由于某种原因我无法匹配正则表达式。我尝试过的命令:

$ csplit jbutryn_us-west-a_neighbors %===.*:% '{20}'
csplit: ===.*:: no match

$ csplit jbutryn_us-west-a_neighbors /===.*:/ '{20}'
552
552
552
csplit: ===.*:: no match

$ csplit jbutryn_us-west-a_neighbors '/===.*:/' '{20}'
552
552
552
csplit: ===.*:: no match

$ csplit -ks -f test jbutryn_us-west-a_neighbors '/===.*:/' '{20}'
csplit: ===.*:: no match

有什么建议么?

答案1

awk解决方案:

awk '/^===/{ fn=substr($NF,2,length($NF)-3) }{ print > fn }' file

每个文件将根据以下内容命名主机名( SERVERNAME<number>)

  • /^===/- 遇到以以下开头的行时===

  • fn=substr($NF,2,length($NF)-3)- 构造文件名fnsubstr($NF,2,length($NF)-3)- 将提取主机名,忽略它周围的括号($NF- 最后一个字段)

  • print > fn- 将底层行打印到文件中

答案2

不要过度指定正则表达式:

$ csplit logfile '/^===/'

这将创建xx00第一部分和xx01第二部分。

或者,如果您还有其他以===该开头的行想要分割:

$ csplit logfile '/^=== Output from/'

要替换xx为另一个固定字符串,请使用-p(不幸的是,无法从输入数据中获取该字符串)。

相关内容