我有一个如下所示的文件:
TITLE Protein in water t= 0.00000
REMARK THIS IS A SIMULATION BOX
ATOM 1 N SER A 107 20.799 63.728 25.985 1.00 0.00 N
ATOM 2 H1 SER A 107 21.658 64.259 25.980 1.00 0.00 H
这是一个非常大的文件:1.6G
略多于 2000 万行。我想得到不以以下内容开头的行ATOM
和结束H
并将它们保存到另一个文件中。做到这一点最有效的方法是什么?
答案1
根据评论的澄清,
sed -n '/^ATOM.*H$/!p' input > output
将从名为 的文件中删除(不打印)以“ATOM”开头并以“H”结尾的行input
,并将其余行打印到名为 的文件中output
。 sed 语法从左到右:
-n
-- 默认不打印行/^ATOM.*H$/
-- 查找以 ATOM 开头、后跟任意数量的字符、$
以 H 结尾 ( ) 的行!p
-- 打印行不匹配上面的模式
输入文件示例:
TITLE Protein in water t= 0.00000
REMARK THIS IS A SIMULATION BOX
ATOM 1 N SER A 107 20.799 63.728 25.985 1.00 0.00 N
ATOM 2 H1 SER A 107 21.658 64.259 25.980 1.00 0.00 H
TITLE Protein in water t= 0.00000H
REMARK THIS IS A SIMULATION BOXH
ATOM 1 N SER A 107 20.799 63.728 25.985 1.00 0.00 N
ATOM 2 H1 SER A 107 21.658 64.259 25.980 1.00 0.00 H
结果是:
TITLE Protein in water t= 0.00000
REMARK THIS IS A SIMULATION BOX
ATOM 1 N SER A 107 20.799 63.728 25.985 1.00 0.00 N
TITLE Protein in water t= 0.00000H
REMARK THIS IS A SIMULATION BOXH
ATOM 1 N SER A 107 20.799 63.728 25.985 1.00 0.00 N
更直接的 sed 语法是:
sed '/^ATOM.*H$/d' input > output
其中说:
- (默认打印行)
- 搜索以 ATOM 开头并以 H 结尾的行
- 删除(不打印)这些行
答案2
根据内容选择行的工具是grep,只要选择内容的规则就可以表示为正则表达式。
“开头为”的正则表达式ATOM
是^ATOM
。 “以”结尾的正则表达式H
是H$
。由于两者不能重叠,因此“以 开头ATOM
,然后包含任何内容,以 结尾H
”的正则表达式为^ATOM.*H$
。
要选择与正则表达式不匹配的行,请使用 选项-v
。
grep -v '^ATOM.*H$' large_file.txt >not_atom_h.txt
对于更一般的条件,尤其是基于列的格式,您可以使用awk。这是一个与示例数据等效的 awk 程序:它打印第一列不是ATOM
或最后一列不是 的行H
。在这种特定情况下,awk 没有任何优势,它会更慢而且不会更简单。我提到它是因为您的问题存在微小的变化,例如,如果在可能或可能不是的列之后添加一列H
,将使使用 grep 解决起来更加困难。
awk '$1 != "ATOM" || $NF != "H"' large_file.txt >not_atom_h.txt
答案3
就命令行长度而言,我能想到的最短的是:
grep -vx ATOM.\*H
就处理速度而言,至少在我的系统上,我发现最快的是:
mawk '!/^ATOM.*H$/'
答案4
(根据下面的评论,这不是最好的解决方案)
你还可以这样做:
grep '[H$]' 源文件 > 目标文件
将“H$”(表示“以 H 结尾”)放在方括号内即可将其否定。因此 grep 将标记与“H$”不匹配的条目