找到模式

时间:2016-11-16 02:45:43

标签: c++ regex shell hashmap pattern-matching

我花了最近2-3天的谷歌搜索和搜索解决方案,但我似乎无法找到任何解决方案。

基本上,我有一个包含数十万条记录的文本文件。这是文件中包含的内容的模式。

  • 第01行:^ D 23554
  • 第02行:Q 123 325
  • 第03行:Y qwe325
  • 第04行:^ P fiwkkwlds
  • 第05行:Y qrwe
  • 06号线:Y rtewt
  • 第07行:^ A 284274 DFL 2939955 001
  • 08行:F 2739
  • 第09行:^ D 23556
  • 第10行:^ k 2994
  • 第11行:^ A 284274 DFL 2939966 002
  • 第12行:^ k 29942
  • 第13行:^ k 32423
  • 第14行:^ A 284274 DFL 2939957 003
  • 第15行:F 23425
  • 第16行:^ A 284274 DFL 2939958 004
  • 第17行:F 92823
  • 第18行:等等......

基本上,数据中没有特定的模式,但每行的开头 - > ^ D,Q,Y,^ P,^ A,F,^ k表示简单的消息。

我希望创建一个脚本(最好是在shell,perl或c ++中),它将从第一行扫描文件,直到最后一行和

1)检索^ A行中的所有值 2)插入分隔符 3)检索^ D行中的最后一个值 4)插入分隔符 5)检索F行中的下一个值 6)希望用数据

创建另一个文本文件

根据我之前的例子,下面是结果:

  • 第01行:284274 DFL 2939955 001 | 23554 | 2739
  • 02号线:284274 DFL 2939966 002 | 23556 | 23425
  • Line 03:284274 DFL 2939957 003 | 23556 | 23425
  • Line 04:284274 DFL 2939958 004 | 23556 | 92823

换句话说:

来自^ A行的值

来自之前^ D行的值|来自下一个F线的价值。

有人可以帮助我吗?我一直在阅读有关哈希映射和哈希表的内容,但我不太清楚如何使用它们。我已经看到很多使用grep的解决方案,你找到一个模式ex:^ A然后在该模式之前/之后打印最后的x行,因为这个数据可以是超级随机的,前面的^ D消息或下一个F消息可以在任何行上。

解决方案有点必须读取文件并始终在内存中保留^ D和F行值并在找到模式^ A时检索它们。

有人可以帮助我:)

谢谢!!!!

3 个答案:

答案 0 :(得分:0)

这是伪代码:

d_value = f_value = null
foreach line in input {
  if line matches ^A {
    print line | d_value | f_value
    d_value = f_value = null
  }
  else if line matches ^D
    a_value = <extracted value>
  else if line matches ^F
    f_value = <extracted value>
}

假设d和f值在a之前。您可以添加错误检查以确保值存在。

希望你这有帮助。

答案 1 :(得分:0)

试试这个正则表达式:

(?<=\^A\s)(?<a>\V+)|(?<=\^D\s)(?<b>\V+)|(?<=\F\s)(?<c>\V+)

它将^A值捕获为组(a),将^D值捕获为组(b),将F值捕获为组(c)。

匹配这些值后,您可以轻松地在此Regex上构建,以使用您选择的任何编程语言对其进行排序。

演示:https://regex101.com/r/2tipn0/1

答案 2 :(得分:-1)

这个可行,但我认为对于大文件来说应该很慢:

IFS=$'\n'
readarray -t -O1 data< <(grep -h -e "\^D" -e "\^A" -e "^F" a.txt)
posA=1
for i in "${data[@]}"; do
if [[ "$i" = "^A"* ]]; then
    textA="${data[$posA]}"
    posD=$posA
    posF=$posA
    textD=""
    textF=""
    while [ "$posD" -ge 1 ] && [[ "$textD" != "^D"* ]]; do
    posD=$(($posD - 1))
    textD="${data[$posD]}"
    done

    while [ "$posF" -le "${#data[@]}" ] && [[ "$textF" != "F"* ]]; do
    posF=$(($posF + 1))
    textF="${data[$posF]}"
    done
    textADF="$textA | $textD | $textF"
    echo "ADF=$textADF"
fi
posA=$(($posA + 1))
done
unset IFS
exit

整个实现基于

的输出
grep -h -e "\^D" -e "\^A" -e "^F" a.txt

存储到数组“data”然后代码操作此数组,并且while循环将在第一个匹配中停止。

也许你可以将grep与head和tail结合起来以避免数组操作。

PS1:同时将-n开关应用于grep可提供有趣的输出。

PS2:我无法使用“^ A ^ D F”组直接grep您的文件,以避免使用代码进行数组操作,但可能是正则表达式可能。