【问题标题】:use sed to return only last line that contains specific string使用 sed 仅返回包含特定字符串的最后一行
【发布时间】:2014-07-31 04:46:38
【问题描述】:

所有帮助将不胜感激,因为我尝试了很多谷歌搜索并画了一个空白:)

我是 sed 新手,不知道我需要什么命令。

我有一个包含很多行的文件,例如

John Smith Aweqwewq321
Mike Smith A2345613213
Jim Smith Ad432143432
Jane Smith A432434324
John Smith Bweqwewq321
Mike Smith B2345613213
Jim Smith Bd432143432
Jane Smith B432434324
John Smith Cweqwewq321
Mike Smith C2345613213
Jim Smith Cd432143432
Jane Smith C432434324

该文件是纯文本且未格式化(即不是 csv 或类似的文件)

我想搜索特定字符串的列表,例如。 John Smith、Mike Smith、Jim Smith 并仅返回文件中找到的每个字符串的最后一行条目(找到的所有其他行都将被删除)。

(我不一定需要每个唯一条目,即可能需要也可能不需要 Jane Smith)

在输出中保持找到的行的原始顺序很重要。

所以结果是:

John Smith Cweqwewq321
Mike Smith C2345613213
Jim Smith Cd432143432

我是 sed 新手,不知道这个命令可能是什么。

大约有 100 个特定的搜索字符串。

谢谢你:)

【问题讨论】:

  • 这将告诉您sed 命令是什么以及如何使用它:man sed。祝你好运
  • 给定列表的格式是什么?
  • @Kent 格式如图所示。它是纯文本。
  • @user1062153 感谢您的回答!我在询问搜索参数您定义的“列表”。不是文件!

标签: linux text sed


【解决方案1】:

假设sample.txt 包含您提供的数据:

$ cat sample.txt
John Smith Aweqwewq321
Mike Smith A2345613213
Jim Smith Ad432143432
Jane Smith A432434324
John Smith Bweqwewq321
Mike Smith B2345613213
Jim Smith Bd432143432
Jane Smith B432434324
John Smith Cweqwewq321
Mike Smith C2345613213
Jim Smith Cd432143432
Jane Smith C432434324

对于这个示例数据,以下脚本可以正常工作:

$ cut -f1,2 -d' ' sample.txt  | sort | uniq | while read s; do tac sample.txt | grep -m1 -n -e "$s" ; done | sort -n -r -t':' | cut -f2 -d':'

John Smith Cweqwewq321
Mike Smith C2345613213
Jim Smith Cd432143432
Jane Smith C432434324

下面是脚本的分解:

  • 首先生成所有唯一字符串(本例中为名字,姓氏)
  • 现在找到这些字符串的最后一次出现。为此,我们通过反转文件找到第一次出现。同时打印行号和输出。
  • 现在以反向行号顺序反转输出,然后删除行号(我们不需要它们)

【讨论】:

    【解决方案2】:
    • 你没有告诉给定列表的格式,我假设它是CSV,和你写的问题一样:eg. John Smith, Mike Smith, Jim Smith

    • 从你的描述来看,你需要each string found这一行,而不仅仅是col1和col2

    从以上两点,我有:

    awk -v list="John Smith, Mike Smith, Jim Smith" 'BEGIN{split(list,p,",\\s*")}
        {for(i=1;i<=length(p);i++){
            if($0~p[i]){
                a[p[i]]=$0
                break
            }
        }
    }END{for(x in a)print a[x]}' file
    

    你可以用你的字符串填充list,用逗号分隔。将其与您的测试数据一起输出:

    John Smith Cweqwewq321
    Mike Smith C2345613213
    Jim Smith Cd432143432
    

    【讨论】:

    • 谢谢 :) 它不是 csv 文件,它是纯文本。很抱歉没有提早提到这一点。
    • @user1062153 你读过我的代码并测试了我的答案吗?我说我假设 列表 是 csv。这里的列表是那些搜索字符串,而不是文件!
    • 谢谢 :) 这行得通。然而,每一行都包含更多信息,包括时间戳。所以需要保留顺序。当我运行代码时,我得到 John Smith Cweqwewq321 Mike Smith C2345613213 Jane Smith C432434324 Jim Smith Cd432143432 的顺序,所以代码改变了行的顺序
    • @user1062153 所以,调整你的帖子以反映真正的需要。
    • @NeronLeVelu :) 好的会做
    【解决方案3】:

    反转列表拳头,例如像这样:

    $ sed -n '/Mike/{p;q}' <(tac input.txt)
    Mike Smith C2345613213
    

    【讨论】:

      【解决方案4】:
      sed -n -e 's/.*/&³/
      H
      $ {x
         s/\n/²/g
         t a
      :a
         s/²\([a-zA-Z]* [a-zA-Z]* \)[^³]*³\(\(.*\)²\1\)/\2/
         t a
         s/²//g;s/³$//;s/³/\
      /g
         p
         }' YourFile
      

      使用任何名称(不能包含 ²³)。对于带有[-a-z-A-Z]的组合名称更改模式

      在您的列表中,还有至少出现一次的Jane Smith

      对于具体的列表,在前面加个grep -f,不用改代码,维护起来更快更容易

      【讨论】:

        猜你喜欢
        • 2012-03-21
        • 2021-12-30
        • 2020-02-20
        • 2020-04-03
        • 2014-09-13
        • 1970-01-01
        • 2012-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多