find -exec grep을 사용하여 기본 이름만 인쇄하거나 파일 이름/줄 내용을 별도의 줄로 분할하려면 어떻게 해야 합니까?

find -exec grep을 사용하여 기본 이름만 인쇄하거나 파일 이름/줄 내용을 별도의 줄로 분할하려면 어떻게 해야 합니까?

소스파일을 보고 있습니다. 실제로 PureBasic의 경우이지만 언어에 관계없이 공통 요소가 있습니다. 제 경우에는 표지 확장 pb, pbipbf다음 명령을 사용합니다 pbp.

find . -name "*.pb*" -exec grep -Hnr ... \;

문제는 이로 인해 full/path/filename.ext:ln#:contents of that line.

두 가지 중 하나를 수행하고 싶습니다. 경로를 완전히 잘라내고( /첫 번째 경로 앞의 마지막 경로 :) 떠나십시오.

filename.ext:ln#:contents of that line

또는 구분선을 사용하여 다음을 수행합니다.

full/path/filename.ext:    
ln#:contents of that line

어느 쪽이든 결과를 더 쉽게 읽을 수 있습니다. 다음과 같은 위치로 분할할 수도 있습니다.

full/path/filename.ext:ln#:  
contents of that line

가독성을 높이기 위해. 나는 유연하다. 그것은 그들 중 하나일 수 있습니다. 한 줄의 명령이나 이러한 특정 명령으로 제한될 필요도 없습니다.

find을 포함 grep하여 내가 찾을 수 있는 모든 나열된 기술을 시도했지만 sed원하는 대로 조합을 구현할 수 없습니다.

답변1

귀하의 설명에 따르면 이 작업을 수행하는 것 같습니다(가로 스크롤을 피하기 위해 4개의 행으로 분할했습니다).

>tmp.txt;
find . -type f -name "*.pb*" \
     -exec grep -Hn pattern "{}" ";" >>tmp.txt;
cat tmp.txt | more

-execdirGnu find를 사용하는 경우 ;를 대신 사용할 수 있습니다 . -exec그러면 명령이 대상 파일의 디렉터리에서 실행되고 grep결과적으로 파일 이름은 해당 디렉터리에 상대적이 됩니다. (지금 바로 ./filename.ext). 그건 아니야상당히요청하신 내용이지만 꽤 가깝고, 사용해야 할 다른 이유도 있습니다 -execdir.

     -execdir grep -Hn pattern "{}" ";"      # See note 1

또 다른 옵션은 중간 쉘을 사용하여 파일 이름 태그를 편집하는 것입니다. 이를 위해서는 Gnu grep옵션이 필요합니다 --label.

     -exec bash -c 'grep -Hn --label="$(basename "$1")" pattern "$1"' \
           _ "{}" ";"

이는 운영 체제에 대해 상당히 길고 더 많은 작업을 수행하지만 ./.

sed두 번째 옵션의 경우 각 줄의 첫 번째(또는 두 번째) 줄 뒤에 개행 문자를 삽입하여 전체 출력을 파이프할 수 있습니다 :.

find . -type f -name "*.pb*" \
     -exec grep -Hn pattern "{}" ";" |
sed 's/:/&\n/' >>tmp.txt.

또는 (두 번째 콜론):

find . -type f -name "*.pb*" \
     -exec grep -Hn pattern "{}" ";" |
sed 's/:[^:]*:/&\n/' >>tmp.txt.

노트

  1. grep에게 재귀적으로( -r) 검색하라고 지시하는 것은 디렉터리를 인수로 제공하지 않기 때문에 의미가 없습니다. find모든 파일이 재귀적으로 발견되었습니다. 그래서 모든 예에서 해당 옵션을 제거했습니다.

  2. cat tmp.txt | more고양이의 쓸모없는 사용(UUOC)입니다. 그냥 사용하세요 more tmp.txt.

  3. ;더 나은 효율성을 위해 Gnu find로 대체되었습니다 +(사용된 예제 제외 bash -c).

답변2

찾고 있는 전제부터 시작하세요.무늬귀하의 파일에는 귀하가 제안한 각 레이아웃에 대한 솔루션이 있습니다.

  1. 경로 이름의 앞부분을 제거합니다.

    find . -name '*.pb*' -type f -execdir grep -Hn 'PATTERN' {} \; | cut -c3- >tmp.txt
    more tmp.txt
    

    참조하는 프로그램을 사용할 때 execdir항상 대상 디렉터리에서 호출되며 현재 파일의 경로 이름은 단순히 ./경로 이름에서 cut -c3-선행을 제거하여 ../

  2. 경로 이름으로 줄을 나누고 줄 번호와 일치 항목을 따릅니다.

    find . -name '*.pb*' -type f -exec grep -Hn 'PATTERN' {} \; | sed 's/:/:\n/' >tmp.txt
    
  3. 경로 이름과 줄 번호를 사용하여 줄을 분할한 다음 일치시킵니다.

    find . -name '*.pb*' -type f -exec grep -Hn 'PATTERN' {} \; | sed 's/^\([^:]*:[^:]*:\)/\1\n/' >tmp.txt
    

    여기서 sed패턴은 두 번째 콜론에서 분할됩니다(RE는 다음과 같이 읽습니다).줄의 시작 부분에서 시작하십시오. 콜론이 뒤에 오는 0개 이상의 콜론이 아닌 문자와 일치합니다. 그리고 다시. 이제 일치 항목을 자체적으로 교체한 다음 래핑하세요.).

파일 이름에 콜론이나 개행 문자가 포함되어 있으면 이러한 해결 방법 중 어느 것도 작동하지 않습니다.

답변3

awk대신 을 사용해 볼 수 있습니다 grep. 예를 들어 기본 이름만 인쇄하면 됩니다.

find . -name '*.pb*' -exec awk 'function basename(file) {
sub(".*/", "", file)
return file
}
/pattern/{
print basename(FILENAME)":"FNR":"$0
}' {} +

경로/줄 내용을 분할합니다.

find . -name '*.pb*' -exec awk '/pattern/{print FILENAME"\n"FNR":"$0}' {} +

또는

find . -name '*.pb*' -exec awk '/pattern/{print FILENAME":"FNR":\n"$0}' {} +

grep파일 이름을 한 번만 인쇄하고 해당 파일에서 일치하는 모든 줄을 두 개의 s 와 함께 인쇄하려는 경우 :

find . -name '*.pb*' -exec grep -l pattern {} \; -exec grep -n pattern {} \;

이는 모든 유형의 파일 이름(콜론이 포함된 파일 이름 포함)에 작동합니다...

답변4

사용grep -l

find . -type f  -exec grep -ilHn --color=always 'searchphrase' {} \;

관련 정보