【问题标题】:Splitting large chunks of text with a regex in Bash在 Bash 中使用正则表达式拆分大块文本
【发布时间】:2018-08-08 13:36:12
【问题描述】:

我有很多要拆分的文本。这很困难,因为从技术上讲,这都是一条线。文本是来自网络设备的未格式化记录消息 - 判断一条消息从何处开始和一条消息在何处结束的唯一方法是消息始终以 '.{5}\d{7}' 开头,例如 <186>1093281。我如何读取该字符串,保存在一个名为“textLog”的文件中并根据该正则表达式将其拆分以形成一个新的字符串/数组以进行干净的输出?

示例输入:

<189>795307: Aug  8 11:41:38 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted<189>795308: Aug  8 11:41:39 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed<189>795309: Aug  8 11:41:45 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted<189>795310: Aug  8 11:41:46 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed<189>795311: Aug  8 11:41:52 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted<189>795312: Aug  8 11:41:53 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed<189>795313: Aug  8 11:41:59 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed<189>795314: Aug  8 11:42:05 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted

(它被格式化为一个长字符串而不是多行。)

期望的输出:一个包含...的数组

arr[0]=<189>795307: Aug  8 11:41:38 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted
arr[1]=<189>795308: Aug  8 11:41:39 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed
arr[2]=<189>795309: Aug  8 11:41:45 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted
...
arr[7]=<189>795314: Aug  8 11:42:05 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted 

它不必是数组或存储在数据结构中,我主要关心的是基于正则表达式的拆分方法,用于输出或保存子字符串。

【问题讨论】:

  • 消息实际上是否以您的示例中的&lt;\d{3}&gt;\d{7} 开头,而不是更通用的.{5}\d{7}
  • 预期输出是什么?可以加个minimal reproducible example吗?
  • @blhsing 你说得对,我只是无法使用 grep(有点新手)让更具体的版本为我工作,所以我选择了更宽松的版本。
  • @BenjaminW。谢谢,本杰明。我尝试添加一个更完整的示例。

标签: regex bash logging split


【解决方案1】:

使用 GNU sed 和 Bash 4.0 或更高版本:

$ mapfile -t arr < <(sed -E 's/(.)(.{5}[[:digit:]]{6})/\1\n\2/g' infile)
$ printf '%s\n' "${arr[@]}"
<189>795307: Aug  8 11:41:38 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted
<189>795308: Aug  8 11:41:39 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed
<189>795309: Aug  8 11:41:45 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted
<189>795310: Aug  8 11:41:46 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed
<189>795311: Aug  8 11:41:52 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted
<189>795312: Aug  8 11:41:53 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed
<189>795313: Aug  8 11:41:59 EDT: %ILPOWER-5-IEEE_DISCONNECT: Interface Gi1/0/8: PD removed
<189>795314: Aug  8 11:42:05 EDT: %ILPOWER-5-POWER_GRANTED: Interface Gi1/0/8: Power granted

sed 命令查找前面有 6 个字符的任何 6 个(而不是问题中暗示的 7 个)数字块,并在第一个字符后插入换行符。这排除了在行首匹配的字符串,我们不想在其中引入换行符。

mapfile 然后通过进程替换将结果读入数组arrprintf 语句每行显示一个数组元素。

或者,根据示例输入,您可以使用 grep 拆分为如下几行:

grep -o '<[^<]*' infile

这假定&lt; 的每次出现都标志着一个新的日志行。

【讨论】:

  • 太棒了!谢谢
猜你喜欢
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 2019-10-14
  • 2022-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多