如何使用 sed 搜索值列表的任何成员
How to search for any member of a list of values with sed
不确定如何恰当地提出问题,但这是用例:
- 我有一个 ~18GB XML 文件 (OpenStreetMap); ~250M 行
- 该文件有约 250 个破坏数据集的违规条目
- 要删除的条目为多行且格式为:
<way id="foo">... <\way>
- 我在文件中有这些 ID
bad_ways
我可以编写一个 for 循环并通过一堆 sed
语句循环,如下所示:
sed -i.bu '/<way id="1_bad_way_entry".*/,/<\/way>/d' in.xml
但是...这需要大约 250 个周期来完成一个 18G 的文件和相关的磁盘写入等,现在每个周期大约需要 18 分钟(旋转磁盘...将通过切换机器很快解决这个问题。更新: SSD 提高到每个周期约 6.5 分钟)。
有什么方法可以让 sed
匹配 bad_ways
中的 任何 条目并在 1 遍中执行此操作?
或者,是否有比 sed
更好的工具?提前致谢!
您可以使用命令替换 assemble 运行 上的 sed
脚本。
(注意:在下面我使用 sed
的 -E
选项来保存一些反斜杠;如果你不这样做,你必须通过包含根据需要反斜杠。)
例如,假设 bad_ways
文件是这样的:
one
two
three
并且 huge_file
是这样的:
everything starts with a zero, then one is next, then two, then three, finally four
您可以使用以下命令完成任务,将 bad_ways
中列出的所有模式替换为 XXX
:
sed -E 's/'"$(sed -zE 's/\n([^$])/|/g' bad_ways)"'/XXX/g' huge_file
则输出为
everything starts with a zero, then XXX is next, then XXX, then XXX, finally four
如您所见,作用于 huge_file
的 sed
脚本是由三个字符串连接而成的:
s/
这是单引号(你应该总是喜欢单引号,除非你需要双引号,如 2.)
sed -zE 's/\n([^$])/|/g' bad_ways
的输出,双引号允许命令替换,并生成 one|two|three
/XXX/g
.
所有这些导致字符串 s/one|two|three/XXX/g
。
这显然不是您的脚本所需的字符串,但我希望这个答案向您展示了一个示例 如何使用命令替换 $(…)
以及使用 [=30 进行适当引用=] 和 "
动态制作命令(sed
、awk
或其他).
事后看来,此答案基于与评论链接中的答案相同的 "philosophy"。但是我不是临时将脚本保存到文件中。如果脚本本身很小(根据您的描述,它很小),这可能不太重要。
不确定如何恰当地提出问题,但这是用例:
- 我有一个 ~18GB XML 文件 (OpenStreetMap); ~250M 行
- 该文件有约 250 个破坏数据集的违规条目
- 要删除的条目为多行且格式为:
<way id="foo">... <\way>
- 我在文件中有这些 ID
bad_ways
我可以编写一个 for 循环并通过一堆 sed
语句循环,如下所示:
sed -i.bu '/<way id="1_bad_way_entry".*/,/<\/way>/d' in.xml
但是...这需要大约 250 个周期来完成一个 18G 的文件和相关的磁盘写入等,现在每个周期大约需要 18 分钟(旋转磁盘...将通过切换机器很快解决这个问题。更新: SSD 提高到每个周期约 6.5 分钟)。
有什么方法可以让 sed
匹配 bad_ways
中的 任何 条目并在 1 遍中执行此操作?
或者,是否有比 sed
更好的工具?提前致谢!
您可以使用命令替换 assemble 运行 上的 sed
脚本。
(注意:在下面我使用 sed
的 -E
选项来保存一些反斜杠;如果你不这样做,你必须通过包含根据需要反斜杠。)
例如,假设 bad_ways
文件是这样的:
one
two
three
并且 huge_file
是这样的:
everything starts with a zero, then one is next, then two, then three, finally four
您可以使用以下命令完成任务,将 bad_ways
中列出的所有模式替换为 XXX
:
sed -E 's/'"$(sed -zE 's/\n([^$])/|/g' bad_ways)"'/XXX/g' huge_file
则输出为
everything starts with a zero, then XXX is next, then XXX, then XXX, finally four
如您所见,作用于 huge_file
的 sed
脚本是由三个字符串连接而成的:
s/
这是单引号(你应该总是喜欢单引号,除非你需要双引号,如 2.)sed -zE 's/\n([^$])/|/g' bad_ways
的输出,双引号允许命令替换,并生成one|two|three
/XXX/g
.
所有这些导致字符串 s/one|two|three/XXX/g
。
这显然不是您的脚本所需的字符串,但我希望这个答案向您展示了一个示例 如何使用命令替换 $(…)
以及使用 [=30 进行适当引用=] 和 "
动态制作命令(sed
、awk
或其他).
事后看来,此答案基于与评论链接中的答案相同的 "philosophy"。但是我不是临时将脚本保存到文件中。如果脚本本身很小(根据您的描述,它很小),这可能不太重要。