【问题标题】:Manipulate txt searching for three pattern (sed,awk,pcregrep)操作文本搜索三种模式(sed、awk、perl grep)
【发布时间】:2017-07-23 06:44:27
【问题描述】:

我有这个文本文件

AAAA
1234
title example
Lorem Ipsum
FF
AAAA
1234
title example
€330 - Roma
FF 

我想从这个文件中只提取以下文本:

START WITH AAAA
HAS Euro SYmbol
END WITH FF

在这种情况下,我只想匹配那个

AAAA
1234
title example
€330 - Roma
FF 

我尝试了不同的解决方案 我用过

sed -e '/AAAAs/,/europ/,/FF/!d' testfile.txt

但它会提取 AAAA 和 FF 之间的所有 txet

我该如何解决?

感谢您的帮助

编辑:

欧元线和FF之间可能有一些文字。我不知道有多少行..

AAAA
1234
title example
€330 - Roma
Some text with \n, comma symbol etc etc
FF

我想提取 AAAA 和 FF 之间的 txt

【问题讨论】:

  • 带有 的行是否总是出现在AAAA 的第4 行和FF 之前?
  • 结构有点棘手,AAAA-A 标题,欧元符号,文本包含\n,和FF
  • 棘手就像在它不需要一直那样吗?
  • 你能试试我的回答看看有没有帮助?
  • @user3720159 如果 SLePort 的回答对您有所帮助,请通过接受他的回答来表明这一点。你可以在What should I do when someone answers my question?找到有关它的信息。

标签: python awk sed text-processing pcregrep


【解决方案1】:

一个不错的快速方法是将 grep 与多个搜索模式一起使用。所以满足您的需求:

grep -B3 -A1 -e '€' test.txt

这将找到欧元符号,并打印之前的 3 行和之后的 2 行,但是这仅在您希望文件保持相同模式时才有效,即 AAAA 和 FF 在上面出现相同数量的行并且下面。

【讨论】:

  • 附带说明,还有很多其他方法可以做到这一点,包括 python re,但是对于搜索大数据,我发现 grep 是最快的。
  • 你能看看 OP 的预期输出吗?你的命令给了AAAA FF AAAA €330 - Roma FF
  • 哦,我明白了 - 在两个参数之间。好的,我会编辑它。
  • 这样它不会返回数字1234
【解决方案2】:

使用 sed:

 sed -n '/^AAAA/{:a;N;/\nFF/!ba; /€/p}' file

工作原理:

  • /^AAAA/:从以AAAA 开头的行开始
  • :a: 标签 a 用于即将到来的循环
  • N: 将下一行添加到模式空间
  • /\nFF/!:如果没有找到后跟FF的换行符,
  • :ba:循环到 a 标签以将下一行添加到模式空间
  • /€/p:如果找到,则输出

编辑:

正如@potong 在 cmets 中所建议的那样,使用 GNU sed 您还可以使用M 命令在多行模式下匹配您的正则表达式:

sed -n '/^AAAA/{:a;N;/^FF/M!ba; /€/p}' file

【讨论】:

  • 如果使用 GNU sed `sed -n '/^AAAA/{:a;N;/^FF/M!ba; /€/p}' 文件也可以上诉。
  • @user3720159 很高兴它有效。我添加了一些解释。
  • @SLePort - 你能解释一下这部分 - "!ba; "
  • @VIPINKUMAR ba 用于循环(b 用于分支)到a 标签。我在答案中为它添加了一行。
【解决方案3】:

Python 是一种过程语言,因此它可能需要更多的文本,但对于复杂的事情来说更简单。在这里你应该:

  • 看到 AAAA 行时开始存储
  • 当您看到 FF 行时结束存储并且
    • 仅在包含 $ 的情况下保留存储的文本

在 Python 中可以翻译为:

with open(infile) as fd:
    processing = False
    txt = None
    euro = None
    for line in fd:
        if line.strip() == 'AAAA':     # start processing
            processing = True
            txt = ""
            euro = False
        if processing:
            txt += line                # store all lines between AAAA and FF
            if '€' in line: euro = True    # is an € present ?
            if line.strip() == 'FF':   # stop processing
                processing = False
                if euro:               # only print if a € was found
                    print(txt)

不像 awk、grep 或 sed 脚本那样紧凑,但易于编写、阅读和维护

【讨论】:

    【解决方案4】:
    awk 'NR>5' file
    
    AAAA
    1234
    title example
    €330 - Roma
    FF 
    

    【讨论】:

      【解决方案5】:
      awk '/\xe2\x82\xac/{printf RS $0}' RS=AAAA file
      

      【讨论】:

      • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
      • 欧元符号 => € => \xe2\x82\xac echo €|hexdump -C
      • 你为什么不使用 /€330/ 而不是一些神秘的东西?像这样: awk '/€330/{printf RS $0}' RS=AAAA 文件
      猜你喜欢
      • 2015-07-19
      • 2017-10-19
      • 2017-09-29
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多