【问题标题】:How to test if a substring from each line of File1 exists in File2如何测试 File1 的每一行的子字符串是否存在于 File2 中
【发布时间】:2019-11-07 20:57:17
【问题描述】:

我有两个包含以下数据的文件

文件 1:

6100540301SD01        ON5330399520191104906781            2019110390678151053303995ACK          20191105
6100540301SD01        ON0403096420191104225695            2019110322569551004030964A            20191105
6005260301SD01        46460045792019110490678911059455    2019110490678951000755694BE3        1120191105
6005260301SD01        46460045792019110490679616020577    2019110490679651000764053BDJDEDH    1620191105

文件2:

20191104
20191105
20191106

由于file1是定宽文件,所以字符位置97到104的字符串是日期。我想按位置从 97 到 104 提取字符串,并检查它是否存在于 file2 中。如果存在,我想将整行复制到 file3。如果不存在,我想将它复制到 file4

我已经创建了 C++ 程序,但是处理 file1 需要很长时间,而几乎有 50 万条记录。因此,如果有任何awk/sed 脚本可以提供帮助,请分享。

【问题讨论】:

  • 您可以使用editor 中的{} 按钮标记数据,或在数据行前添加四个空格。
  • @Adeel :在速度方面,我不认为你可以用 awk 击败 C++,所以问题可能更多是关于你的算法的效率,我之前会关注这个问题思考,使用哪种编程语言。
  • @Adeel :如果您可以提供一些 file2 的大小信息,也会有所帮助。例如,Barmer 的回答很好,除非 file2 很大。
  • @user1934428,是的,你是对的,算法很重要。文件 2 很小,最多有 80 条记录。我已经尝试使用随机访问 STL 容器,但是是的,仍然可以改进算法,因为我的算法的成本是线性的,这对于拥有 50 万条记录的大型文件 1 来说成本很高。
  • 请发布时间信息。什么是太长了?最多不超过几秒钟。

标签: linux shell awk sed


【解决方案1】:

awk 来救援!

$ awk 'NR==FNR {dates[$0]; next} 
               {print > (substr($0,97,104) in dates?"file3":"file4")}' file2 file1

【讨论】:

    【解决方案2】:

    file2 的内容转换为像20191104|20191106|20191106 这样的正则表达式。然后就可以用grep来匹配了。

    patterns=$(<file2)
    # Replace newlines with |
    pattern=${patterns//$'\n'/|}
    # Put ^.{96} at the beginning so it matches starting at column 97
    pattern="^.{96}($pattern)"
    grep -E "$pattern" file1 > file3 # Lines that match
    grep -v -E "$pattern" file1 > file4 # Lines that don't match
    

    如果运行grep两次太慢,你可以使用awk

    awk -v pat="$pattern" '$0 ~ pat { print >>"file3"; next} {print >>"file4"}'
    

    【讨论】:

      【解决方案3】:

      这可能对你有用(GNU sed):

      sed 's#.*#/^.\\{96\\}&/ba#' file2 | sed -nf - -e 'w file4' -e 'b;:a;w file3' file1
      

      从 file2 创建一个脚本,将每个匹配项写入 file3 并将任何剩余的行写入 file4。

      第一次调用 sed 将其输出传递给第二次调用 sed,第二次调用又补充了一对内联命令字符串。所有匹配都被发送到循环持有者:a,它将它们写到file3中,任何不匹配的都被写入file4。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-17
        • 1970-01-01
        • 2021-06-27
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2017-02-21
        • 1970-01-01
        相关资源
        最近更新 更多