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그렇게 하면 아마도 더 좋을 것입니다... 저는 주로 동일한 목표 달성을 보여주기 위해 이 방법을 썼습니다. 궁극적인 목표.

관련 정보