Linux에서 다음과 같은 파일 콘텐츠 검색 명령을 원합니다.
- md, txt, htm과 같은 지정된 파일을 검색합니다.
- 폴더 및 해당 하위 폴더에서 반복적으로 실행(예: ).
- 콘텐츠 검색은 정규식 패턴일 수 있습니다(예: tomat.*es).
- 일치하는 항목 주변의 텍스트를 출력합니다.
- 출력은 다음 형식입니다., 각 파일을 빈 줄로 구분합니다.
file1 lineNr1:text1 lineNr2:text2 file2 lineNr1:text1 lineNr2:text2
6/마지막 기준인 출력은 시각적으로 명확해야 합니다., 따라서 터미널에서 grep과 같은 색상 구성표를 사용하십시오.
- 파일 색상은 color_1(예: 보라색)입니다.
- color_2의 lineNr(예: 녹색)
- 텍스트 출력의 경우:
- color_3의 텍스트를 일치시킵니다(예: 빨간색).
- 나머지 텍스트는 color_4입니다(예: 흰색).
원래,grep이 작업을 수행하지만 출력 형식을 변경하고 싶습니다.,지금 바로:
file1:lineNr1:text1
file1:lineNr2:text2
file2:lineNr1:text1
file2:lineNr2:text2
제가 원하는 것은 검색 결과에 집중하는 것인데, 디렉토리 검색을 할 때 검색 결과 앞에 파일 경로명이 있으면 검색이 더 복잡해집니다. 파일에 일치하는 항목이 여러 개 있는 경우. 내가 원하는 것은 각 파일이 내가 찾고 있는 것을 직접 볼 수 있는 것입니다. 파일, 하위 폴더 및 일치 항목이 많을수록 명확한 초점이 더 중요해집니다.
따라서 grep은 긴 출력을 제공하고 포커스를 잃습니다. 아마도 grep 명령의 새로운 기능으로 요청되어야 할 것입니다.
나는 내가 원하는 것에 가깝습니다.
test.txt에 다음 두 문장이 있다고 가정합니다.
2023-09-25: after colon char does not output the sentence.
2023-09-25 outputs line as there is NO colon preceding match.
그런 다음 다음 cli를 실행합니다.
grep -rwn --include=\*.{md,txt} -ie "output.*" --color=always | awk -F: '{if(f!=$1)print "\n"$1; f=$1; print $2 ":" $3;}'
이 예에서 첫 번째 줄의 출력은 ":"에서 중지되는 반면 두 번째 줄의 경우 아름다운 출력이 표시됩니다. 첨부 파일을 참조
따라서 일치하는 텍스트에 콜론 ":"이 포함되어 있지 않으면 이 쿼리는 작업을 수행합니다. 일치 항목 주위에 텍스트 출력이 없으므로 검색 출력의 유용성이 떨어집니다.
더 복잡한 예(txt 파일을 첨부할 수 없음):
utf-8 encoded
# We're interested in searching on the word: tomato or tomate in french
In markdown file it can be put in bold using **tomatoes**
In a html file, content is full of tags, put a word in bold can be put in many way, such as <b>tomato</b>
Let's see what the search will return on these combinations:
1. At 6:45 will eat tomato soup.
2. Tomatoes were cooked for the soup recipe, but what time do we eat tomato soup? Isn't it six forty-five, aka 6:45?
3. Tomate en français
4. tomates: pluriel du mot tomate.
Could be tricky to restrict search only on bilingual TOMATO's variation, as for instance in automatically, there is auTOMATically.
Regular expression are of help.
일치 항목이 2개의 하위 폴더에 있다고 가정하면 이 CLI는 다음과 같이 명확하게 설명합니다.
grep -rn --include=\*.{md,txt} -iP "tomat[eo]s*" --color=always | awk -F: '{if(f!=$1)print "\n"$1; f=$1; print $2 ":" $3;}'
그러나 추가 출력콜론 문자 ":" 이후의 내용은 출력에 나타날 수 없습니다., 콜론 ":"을 ";"으로 바꾸면 차이점을 볼 수 있습니다.
이제 출력 검색 결과를 일반 텍스트 파일로 덤프하려는 경우 색 구성표가 손실되면 시각적 정보가 손실됩니다. 따라서 태그가 포함된 html 파일은 색상 정보를 복구합니다.이 작업은 다음과 같은 html 출력으로 수행할 수 있습니다.:
<div class="grep">
<p class="grep_file">file_1</p>
<span class="grep_line">lineNr1</span>:beginning of surrounding match<span class="grep_match">SEARCH_PATTERN</span>end of surrounding match<br>
<span class="grep_line">lineNr2</span>:beginning of surrounding match<span class="grep_match">SEARCH_PATTERN</span>end of surrounding match<br>
</div>
<div class="grep">
<p class="grep_file">file_2</p>
<span class="grep_line">lineNr1</span>:beginning of surrounding match<span class="grep_match">SEARCH_PATTERN</span>end of surrounding match<br>
<span class="grep_line">lineNr2</span>:beginning of surrounding match<span class="grep_match">SEARCH_PATTERN</span>end of surrounding match<br>
</div>
스타일 클래스를 통해 색상 구성표를 얻을 수 있습니다.
이제 grep과 awk를 사용해 보았지만 다른 조합이 작업에 더 나은 아이디어일 수 있습니다.
감사해요
답변1
나생각하다당신이 원하는 것은 다음과 같습니다.
$ grep -rwn --include=\*.{md,txt} -ie "output.*" --color=always | awk -F: '{if(f!=$1){print "\n"$1;}f=$1; $1=""; }1'
file.txt
1 2023-09-25 after colon char does not output the sentence.
2 2023-09-25 outputs line as there is NO colon preceding match.
file1.txt
1 2023-09-25 after colon char does not output the sentence.
2 2023-09-25 outputs line as there is NO colon preceding match.
다음과 같습니다.
접근 방식의 문제점은 :
필드 구분 기호로 사용하고 필드 2와 3만 명시적으로 인쇄한다는 것입니다. 따라서 :
행에 더 많은 필드가 있으면 나머지 필드를 놓칠 수 있습니다. 여기서 하는 일은 첫 번째 필드( $1=""
)를 지운 다음 전체 줄을 인쇄하는 것입니다( 1;
줄을 인쇄합니다. 에서 awk
어떤 항목이 true로 평가되고 항상 true로 평가되면 기본 작업은 해당 1
줄을 인쇄하는 것입니다).
awk
명확성을 위해 코드를 다음과 같이 확장 할 수 있습니다 .
awk -F: '
{
## If this is a new file name, print the file name
if ( f != $1 ){
print "\n"$1
}
## save the 1st field in the variable f
f=$1
## clear the first field
$1=""
## print the line
print
}'
중요한: 파일 이름 자체에 :
. file:weird.txt
이를 처리하는 것은 가능하지만 더 많은 스크립팅이 필요하므로 이것이 문제인 경우 더 많은 예제 파일 이름을 포함하도록 질문을 업데이트하거나 새 질문을 게시하십시오.
답변2
이 명령을 사용하면 다음을 제공할 수 있습니다.
grep -rwn --include=\*.{md,txt} -ie "output.*" --color=always |
awk -F: '{if(f!=$1)print "\n"$1; f=$1; print $2 ":" $3;}'
output.*
파일에서 대문자 또는 소문자와 일치하는 문자열을 포함하거나 다음으로 끝나는 줄을 찾으려고 하는 것 같습니다 . 그건:.md
.txt
find . -type f \( -name '*.md' -o -name '*.txt' \) -exec \
grep -Hin 'output' \
{} +
그런 다음 해당 출력을 awk로 파이프하면 다시 이 출력이 변경됩니다.
file1:lineNr1:text1
file1:lineNr2:text2
file2:lineNr1:text1
file2:lineNr1:text2
이와 관련하여:
file1
lineNr1:text1
lineNr2:text2
file2
lineNr1:text1
lineNr2:text2
따라서 화면에 인쇄를 구현하는 데 도움이 필요한 내용은 다음과 같습니다.
$ grep -rwn --include=\*.{md,txt} -ie "output.*" --color=always |
awk -F':' '{p=f; f=$1; sub(/[^:]+:/,"")} f!=p{print sep f; sep=ORS} 1'
test.txt
1:2023-09-25: after colon char does not output the sentence.
2:2023-09-25 outputs line as there is NO colon preceding match.
grep
그러나 결과를 읽을 때 결과 색상을 지정하는 데 사용된 ASCII 이스케이프 시퀀스가 이미 출력에 존재하므로 awk
ASCII 이스케이프 시퀀스 대신 HTML 태그를 생성하려면 이를 포함하도록 awk 스크립트를 업데이트해야 합니다. 입력 이러한 이스케이프 시퀀스를 찾아서 HTML 태그로 변환합니다. 이는 약간 뒤떨어지고 깨지기 쉽습니다(예: 일부 이스케이프 시퀀스가 원래 입력에 존재하면 어떻게 될까요? 이러한 이스케이프 시퀀스와 다음에 의해 추가된 것을 구별할 수 있는 방법이 없습니다. grep) vs. 원본 입력 파일에서 grep 대신 awk를 실행하고 awk가 원하는 색상 문자열을 인쇄하도록 하세요.
원하는 레이아웃으로 무색 텍스트를 인쇄하려면 find+grep의 출력을 awk로 파이프하는 대신 grep을 awk로 바꿀 수 있습니다.
find . -type f \( -name '*.md' -o -name '*.txt' \) -exec \
awk '
tolower($0) ~ /output/ {
if ( !seen[FILENAME]++ ) {
print ORS FILENAME
}
print
}
' \
{} +
출력에 색상을 사용하려면 awk 스크립트를 업데이트하여 이스케이프 시퀀스나 HTML 태그 또는 원하는 색상, 원하는 텍스트를 인쇄하세요.https://unix.stackexchange.com/a/669122/133219그리고https://stackoverflow.com/questions/64034385/using-awk-to-color-the-output-in-bash/64046525#64046525화면의 색상으로 이 작업을 수행하는 방법에 대한 자세한 내용은 다음을 참조하세요.https://stackoverflow.com/a/40722767/1745001그리고https://stackoverflow.com/a/39193330/1745001HTML 출력에 색상을 지정하는 방법을 알아보세요.
다음은 bash 스크립트에서 find+awk를 사용하여 화면에 인쇄하려는 출력 형식을 지정하는 예입니다.
$ cat tst.sh
#!/usr/bin/env bash
tput sc
trap 'tput rc; exit' EXIT
colors=( reset red green yellow blue purple )
for colorNr in "${!colors[@]}"; do
fgColorMap+=( "${colors[colorNr]} $(tput setaf $colorNr)" )
done
find . -type f \( -name '*.md' -o -name '*.txt' \) -exec \
awk -v fgColorMap="${fgColorMap[*]}" '
BEGIN {
OFS = ":"
split(fgColorMap,tmp)
for ( i=1; i in tmp; i+=2 ) {
fg[tmp[i]] = tmp[i+1]
}
}
match(tolower($0),/output.*/) {
if ( !seen[FILENAME]++ ) {
if ( found++ ) { print "" }
print fg["purple"] FILENAME fg["reset"]
}
print fg["green"] FNR ":" fg["reset"] \
substr($0,1,RSTART-1) \
fg["red"] substr($0,RSTART,RLENGTH) fg["reset"] \
substr($0,RSTART+RLENGTH)
}
END { if ( found ) print "" }
' \
{} +
보이는 텍스트 출력은 다음과 같습니다.
$ ./tst.sh
./test.txt
1:2023-09-25: after colon char does not output the sentence.
2:2023-09-25 outputs line as there is NO colon preceding match.
이는 동일하지만 색상 코드가 표시됩니다.
$ ./tst.sh | cat -A
^[7^[[35m./test.txt^[[30m$
^[[32m1:^[[30m2023-09-25: after colon char does not ^[[31moutput the sentence.^[[30m$
^[[32m2:^[[30m2023-09-25 ^[[31moutputs line as there is NO colon preceding match.^[[30m$
$
^[8$
컬러 출력은 다음과 같습니다.
HTML을 얻으려면 awk 스크립트를 변경하여 원하는 HTML을 인쇄하세요. 질문에 예상되는 HTML 출력이 표시되지 않아 원하는 것을 표시하지 않았기 때문에 원하는 것을 얻는 데 도움을 드릴 수 없습니다. 그러나 사용할 수 있는 기존 예제가 많이 있습니다(참조 I' 참조). 위에 정보를 제공했습니다). 따라서 어떻게 해야 할지 모르신다면 나중에 새로운 질문을 하셔도 됩니다.