소스파일을 보고 있습니다. 실제로 PureBasic의 경우이지만 언어에 관계없이 공통 요소가 있습니다. 제 경우에는 표지 확장 pb
, pbi
및 pbf
다음 명령을 사용합니다 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
-execdir
Gnu 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.
노트
grep에게 재귀적으로(
-r
) 검색하라고 지시하는 것은 디렉터리를 인수로 제공하지 않기 때문에 의미가 없습니다.find
모든 파일이 재귀적으로 발견되었습니다. 그래서 모든 예에서 해당 옵션을 제거했습니다.cat tmp.txt | more
고양이의 쓸모없는 사용(UUOC)입니다. 그냥 사용하세요more tmp.txt
.;
더 나은 효율성을 위해 Gnu find로 대체되었습니다+
(사용된 예제 제외bash -c
).
답변2
찾고 있는 전제부터 시작하세요.무늬귀하의 파일에는 귀하가 제안한 각 레이아웃에 대한 솔루션이 있습니다.
경로 이름의 앞부분을 제거합니다.
find . -name '*.pb*' -type f -execdir grep -Hn 'PATTERN' {} \; | cut -c3- >tmp.txt more tmp.txt
참조하는 프로그램을 사용할 때
execdir
항상 대상 디렉터리에서 호출되며 현재 파일의 경로 이름은 단순히./
경로 이름에서cut -c3-
선행을 제거하여 ../
경로 이름으로 줄을 나누고 줄 번호와 일치 항목을 따릅니다.
find . -name '*.pb*' -type f -exec grep -Hn 'PATTERN' {} \; | sed 's/:/:\n/' >tmp.txt
경로 이름과 줄 번호를 사용하여 줄을 분할한 다음 일치시킵니다.
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' {} \;