두 파일에 다음 내용이 있다고 가정합니다.
$ cat ttest1.txt
x = 1
x = 3
y = 5
$ cat ttest2.txt
x = 4
x = 10
y = 3
x
파일을 재귀적으로 grep 하고 각 파일의 마지막 인스턴스를 인쇄하고 싶습니다 . 따라서 원하는 출력은 다음과 같습니다.
ttest1.txt:x = 3
ttest2.txt:x = 10
다음과 의 grep
조합은 tail
하나의 파일에 대해 작동하지만 여러 파일에 대해서는 작동하지 않습니다.
$ grep x ttest1.txt
x = 1
x = 3
$ grep x ttest1.txt | tail -n 1
x = 3
$ grep -r x ttest* | tail -n 1
ttest2.txt:x = 10
이 문제를 어떻게 해결할 수 있나요?
답변1
당신이 할 때
grep -r x ttest*
당신은 스트림을 얻습니다
ttest1.txt:x = 1
ttest1.txt:x = 3
ttest2.txt:x = 4
ttest2.txt:x = 10
이렇게 하면 예상한 대로 tail -1
입니다 ttest2.txt:x = 10
.
grep | tail
그러나 병합된 스트림이 아닌 각 개별 파일에서 결합이 수행되기를 원합니다 . 따라서 각 개별 파일에 대해 이 작업을 수행하십시오.
for f in ttest* ; do
grep x "$f" | tail -n 1
done
답변2
를 사용하면 awk
정규식 문자열을 사용할 수 있습니다(참조:동적 정규식), 각 입력 파일의 마지막 일치 항목을 기억하고 인쇄합니다.
$ awk -v regex="x" 'FNR==1 && m!=""{print m;m=""}
$0 ~ regex{m=FILENAME ":" $0}
END{if (m!="")print m}' ttest*
ttest1.txt:x = 3
ttest2.txt:x = 10
다음과 재귀적으로 결합됩니다 find
.
$ find . -name 'ttest*' -type f -exec awk -v regex="x" '
FNR==1 && m!=""{print m;m=""}
$0 ~ regex{m=FILENAME ":" $0}
END{if (m!="")print m}' {} +
./ttest1.txt:x = 3
./ttest2.txt:x = 10
답변3
GNU sed 사용:
sed -sn '/x/h; $ { x; F; p; }' ttest*
산출:
ttest1.txt
x = 3
ttest2.txt
x = 10
paste -d: - -
결과를 한 행에 표시하려면 이 옵션을 전달하세요. -change 명령 x
뒤에 검사가 포함되지 않은 파일에서 출력 하지 않으려는 경우 x
예를 들면 다음과 같습니다.{ x; /./ { F; p; z; }; }
답변4
한 가지 방법은 다음과 같습니다.
grep x <yourpath>* | tac | awk 'BEGIN{FS=":"};seen!=$1{print $0;seen=$1}'
tac은 awk 작업을 준비하기 위해 grep 결과를 뒤집은 다음 각 파일에서 첫 번째 일치 항목만 인쇄합니다.