【问题标题】:Cut and paste a line with an exact match using sed使用 sed 剪切并粘贴完全匹配的行
【发布时间】:2013-10-02 03:22:26
【问题描述】:

我有一个文本文件 (~8 GB)。让我们将此文件称为 A。文件 A 大约有 100,000 行,其中 19 个单词和整数由空格分隔。我需要从文件 A 中剪切几行并将它们粘贴到一个新文件(文件 B)中。应从文件 A 中删除这些行。从文件 A 中删除的行应具有完全匹配的字符串。 然后我需要重复几次,每次从文件 A 中删除具有不同匹配字符串的行。每次,文件 A 都在变小。 我可以使用“sed”但使用两个命令来做到这一点,如下所示:

# Finding lines in file A with matching string and copying those lines to file B
sed -ne '/\<matchingString\>/ p' file A > file B

#Again finding the lines in file A with matching string and deleting those lines,
#writing a tmp file to hold the lines that were not deleted.
sed '/\<matchingString\>/d'file A > tmp

# Replacing file A with the tmp file.
mv tmp file A

这是文件 A 和 B 的示例。我想提取所有包含 hg15 的行 文件 A:

ID pos frac xp mf ...
23 43210 0.1 2 hg15...
...
...

File B:
23 43210 0.1 2 hg15...

我对编写 shell 脚本和使用所有 Unix 工具还很陌生,但我觉得我应该能够更优雅、更快地完成这件事。谁能指导我改进这个脚本。我不需要特别使用“sed”。我一直在搜索 web 和 stackoverflow,但没有找到解决这个确切问题的方法。我正在使用 RedHat 和 bash。 谢谢。

【问题讨论】:

  • 你能发布一些输入和预期输出的示例数据吗?当我们不需要猜测时,让我们的生活变得如此轻松:-)

标签: shell unix sed paste cut


【解决方案1】:

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

sed 's|.*|/\\<&\\>/{w fileB\nd}|' matchingString_file | sed -i.bak -f - fileA

这会从匹配的字符串中创建一个 sed 脚本,将匹配的行写入 fileB 并从 fileA 中删除它们。

注意文件A的备份也被制作了。

要为每个完全匹配的单词创建不同的文件,请使用:

sed 's|.*|/\\<&\\>/{w "&.txt"\nd}|' matchingString_file | sed -i.bak -f - fileA

【讨论】:

  • 您能否解释一下这段代码在步骤中的作用。有一件事我没有说清楚。我需要为每个完全匹配的单词编写一个不同的 fileB。
  • 这个解决方案效果很好,比我自己的脚本快一点。
【解决方案2】:

我会为此使用grep,但除了这个小改进之外,这可能是最快的方法了,即使这意味着将正则表达式应用于每行两次:

grep '<matchingString>' A > B
grep -v '<matchingString>' A > tmp
mv tmp A

下一个方法是逐行读取文件,检查该行,然后根据检查将其写入Btmp。 (最后又是mv tmp A。)但是没有标准的Unix工具可以做到这一点(AFAIK),在shell中这样做可能会大大降低性能:

while IFS='' read line
do
    if expr "$line" : '<matchingString>' >/dev/null
    then
        echo "$line" 1>&3
    else
        echo "$line"
    fi > B 3> tmp
done < A

您可以尝试使用 Python(或类似的脚本语言)来执行此操作:

import re
with open('B', 'w') as b:
  with open('tmp', 'w') as tmp:
    with open('A') as a:
      for line in a:
        if re.match(r'<matchingString>', line):
          b.write(line)
        else:
          tmp.write(line)
os.rename('tmp', 'A')

但这有点超出范围(不再是 shell)。

【讨论】:

    【解决方案3】:

    希望对你有帮助……

    cat File A | while read line     
    do        
    
        #Finding lines in file A wit matching string and copying those lines to file B
        sed -ne '/\<matchingString\>/ p' file A >> file B
    
        #Again finding the lines in file A with matching string and deleting those lines  
        #writing a tmp file to hold the lines that were not deleted     
        sed '/\<matchingString\>/d'file A >> tmp
    
    done
    
    #once you are done with greping and copy pasting Replacing file A with the tmp file    
    `mv tmp file A`
    

    PS:我正在附加到文件 B,因为当找到匹配模式时,我们正在循环中查找。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-14
      • 1970-01-01
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多