Markdownファイル検索のために出力をかなりgrepする方法は?

Markdownファイル検索のために出力をかなりgrepする方法は?

Markdownファイルストア(別名Zettelkasten)があります。次のコマンドを使用して検索しますgrep -irn 'search request' *.md。すべてが正常です。

ところで、検索された文字列のファイルタイトルとサブタイトルが出力された内容を見たいと思います。

はい

ファイル.md

1 # Title
2
3 ## Subtitle
4
5 yada-yada

出力

> grep -irn 'yada' *.md

< file.md:5:Title:Subtitle:yada-yada

grepファイルを何度も検索せずにこれを実行できますか?

似たようなもの覚える端末に最適です。

ベストアンサー1

いいえ、grepはそうすることはできません。ただし、awkまたはPerlを使用して独自のカスタム検索ツールを簡単に作成できます。例えば

find ./ -name '*.md' -exec awk -v search="yada-yada" '
  /^# /  { title=$0;    sub(/^# /,"",title)     };
  /^## / { subtitle=$0; sub(/^## /,"",subtitle) };
  $0 ~ search { printf "%s:%i:%s:%s:%s\n", FILENAME,FNR,title,subtitle,$0 }' {} +

これは、特定の要件に合わせてカスタマイズまたは大幅に改善できる非常に独創的な例です。 .-v search="$1""yada-yada"

これはPerlで書かれた少し良いバージョンです。これは必要ありませんfind(Perl固有ファイル::検索モジュール)とより良いオプション処理により、拡張が容易になる可能性があります(たとえば、同様の複数のディレクトリ検索をサポートしたり、grepや他のプログラムと同様にオプションを追加したり、大文字と小文字をfind区別しない、または-i-vマッチングをサポートできます) 。

#!/usr/bin/perl

use strict;
use File::Find;

# Very primitive argument handling, should use Getopt::Long or
# one of the other Getopt::* modules
my $path   = shift;    # first arg is dir to search, e.g. './'
my $search = shift;    # second arg is regex to search for

find({ wanted => \&wanted, no_chdir => 1}, $path);

sub wanted {
  # This uses \z in the regex rather than just $ because
  # filenames can contain newlines.
  next unless (-f $File::Find::name && /\.md\z/s);
  
  # open the file and "grep" it.
  open(my $fh, "<", $File::Find::name) || warn "couldn't open $File::Find::name: $!\n";
  
  my $title    = '';
  my $subtitle = '';
  
  while(<$fh>) {
    chomp;
    
    if (/^# /) {
      ($title = $_) =~ s/^# //;
    
    } elsif (/^## /) { 
      ($subtitle = $_) =~ s/^## //;
    
    } elsif (/$search/) {
      printf "%s:%i:%s:%s:%s\n", $File::Find::name, $., $title, $subtitle, $_;
      
      # uncomment the next line if you want only the first match in
      # any given file (i.e. same as '-m 1' with grep):
      # close $fh;
    }
  };
  close($fh);
}

実行例:

$ ./grep-md.pl ./ yada-yada
./file.md:5:Title:Subtitle:yada-yada
./file2.md:5:Another Title:And Another Subtitle:yada-yada
./sub/dir/several/levels/deep/file3.md:5:Third Title:File Three Subtitle:yada-yada

ただし、File::Find を使用してファイルを検索するのではなく、ファイルを検索するために作成することもできます。find ... -execそうすれば、おそらくより良いでしょう...私は主に同じ目標を達成するためにこの方法を書きました。究極の目標。

おすすめ記事