如何挑选出标题包含特定文本的文件夹中的文件?

如何挑选出标题包含特定文本的文件夹中的文件?

用例:假设有一个充满大型 RDF+XML 文件的文件夹,并且它们遵循不同的名称空间。我们想要找到那些遵循给定名称空间的文件(例如xmlns:crm="http://www.cidoc-crm.org/cidoc-crm#")。

从上到下扫描文件非常耗时,因为名称空间始终定义在 XML 文件的前几行中。

如何在一个巨大的文件夹中挑选出标题包含特定文本的文件?

答案1

答案看起来像这样:

 awk '/hi/ { if (FNR >= 5) { nextfile }; print FNR, FILENAME }' *

使用正则表达式匹配字符串更改/hi/。将 更改5为您要查看的标题中的最后一个行号。

答案2

awk如果您支持,则仅查看前 5 行nextfile

TEXT='xmlns:crm="http://www.cidoc-crm.org/cidoc-crm#"' \
  find . -type f -exec awk '
     index($0, ENVIRON["TEXT"]) {print FILENAME; nextfile}
     FNR == 5 {nextfile}' {} +

(如果您awk不支持nextfile,它将被默默地忽略并且文件将被完全读取)。

或者你可以使用perl

TEXT='xmlns:crm="http://www.cidoc-crm.org/cidoc-crm#"' \
  find . -type f -exec perl -Tne '
     if (index($_, $ENV{"TEXT"}) >= 0) {print "$ARGV\n"; close ARGV}
     elsif ($. == 5) {close ARGV}' {} +

答案3

如果您的所有文件都有名称空间声明,则使用 GNU/FreeBSD/OSX grep 或任何具有该-m选项的实现,您可以查找名称空间声明并在找到后立即退出,然后将结果通过管道传输到第二个 grep 以获得您感兴趣的命名空间。

grep -m xmlns: *.xml  |grep 'xmlns:crm="http://www.cidoc-crm.org/cidoc-crm#"'

如果某些文件缺少可识别的命名空间声明或其他一些表示“退出”的模式,请使用 sed 或 awk 来根据行号指定退出条件。使用 sed,无法计算每个文件的行数,因此您需要对每个文件调用 sed:

for x in *.xml; do
  if [ -n "$(sed -n -e 's/.*xmlns:crm="http:\/\/www.cidoc-crm.org\/cidoc-crm#".*/1/' -e '/xmlns:/q' -e '5q')" ]; then
    printf '%s\n' "$x"
  fi
done

斯特凡·查泽拉斯的回答awk 解决方案。

任何基于文本处理工具的方法都是本质上脆弱。例如,它会选取一个被注释掉的命名空间声明。除非您要手动查看结果或者您知道所有文件都具有“驯服”结构(没有注释、没有与您正在搜索的内容类似的有效负载文本等),否则您应该使用适当的 XML 解析器相反 - 但会更慢。

相关内容