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
そうすれば、おそらくより良いでしょう...私は主に同じ目標を達成するためにこの方法を書きました。究極の目標。