다음과 같은 텍스트 파일이 있습니다.
Doc_A 123 abc
Doc_A 456 def
Doc_A 789 ghi
Doc_B 123 abc
Doc_B 456 def
Doc_C 123 abc
Doc_C 456 def
Doc_C 789 ghi
Doc_C 101 jkl
및 참고 문서
Doc_A
Doc_B
Doc_C
Doc_D
Doc_E
Doc_F
참조 파일의 이름과 일치하는 텍스트 파일의 첫 번째 줄을 추출하고 해당 줄을 인쇄하거나, 일치하는 항목이 없으면 다음과 같이 특정 고정 패턴을 인쇄하고 싶습니다.
Doc_A 123 abc
Doc_B 123 abc
Doc_C 123 abc
Doc_D 10 20
Doc_E 10 20
Doc_F 10 20
아래와 같이 awk를 사용하여 일치하는 패턴을 인쇄할 수 있습니다. 요구 사항에 따라 고정된 방식으로 찾을 수 없는 패턴을 어떻게 인쇄할 수 있습니까?
awk 'FNR == NR { a[$1] = 0; } FNR != NR { for (i in a) if ($0 ~ i && a[i]++ == 0) { print $0; break; } }' \ref.txt file.txt
답변1
일치하는 항목을 조회 배열에서 제거한 다음 끝에 남은 항목을 인쇄하는 것은 어떻습니까?
$ awk 'NR==FNR {a[$1]; next}
$1 in a {print; delete a[$1]}
END {for (i in a) print i, "10 20"}
' ref.txt file.txt
Doc_A 123 abc
Doc_B 123 abc
Doc_C 123 abc
Doc_D 10 20
Doc_E 10 20
Doc_F 10 20
(awk는 배열 순회 순서를 보장하지 않습니다. 문제가 있는 경우)
설명하다
그 동안 NR==FNR
우리는 첫 번째 명명된 파일( ref.txt
)에 대해 작업하고 있습니다. 첫 번째(이 경우 고유한) 필드로 색인이 지정된 배열 항목을 만든 다음 레코드로 이동합니다 next
. 배열 요소에 값을 할당할 필요가 없습니다.
그렇지 않으면 두 번째 명명된 파일( )을 처리 중입니다 file.txt
. 첫 번째 열이 참조 파일에서 구성한 배열과 일치하는지 확인하고 a
일치하면 레코드를 인쇄합니다. $0
그런 다음 항목을 삭제합니다.
제거는 두 가지 목적으로 사용됩니다. 다음에 $1 in a
동일한 항목을 테스트할 때 $1
대답은 거짓이 되기 때문에 일치 항목을 "고유하게" 합니다. 이는 또한 file.txt
모든 행이 처리된 후에도 의 나머지 요소가 a
아직 일치하지 않음을 의미합니다. END
이를 블록의 "고정" 형식으로 인쇄할 수 있습니다.
답변2
작업에 awk가 필요합니까? grep
도 가능.
파일이 공백으로 구분된 것 같습니다. 아래 솔루션은 참조 파일의 고정 패턴에 공백이 포함되지 않는다는 가정을 기반으로 합니다.
file.txt
텍스트 파일을 ref.txt
.
$ for P in $(cat ref.txt); do grep -m1 "^$P[[:blank:]]" file.txt || printf "%s 10 20\n" "$P"; done
Doc_A 123 abc
Doc_B 123 abc
Doc_C 123 abc
Doc_D 10 20
Doc_E 10 20
Doc_F 10 20
답변3
다음과 같은 다양한 방법으로 이 작업을 수행할 수 있습니다.
awk '
NR == FNR && !($1 in a){a[$1]=$0}
NR != FNR{print ($1 in a) ? a[$1] : $1" 10 20"}
' inp ref.txt
perl -lane '
$h{$F[0]} = $_ unless exists $h{$F[0]}}{
while ( <STDIN> ) {
chomp;
print(exists $h{$_} ? $h{$_} : qq<$_ 10 20>);
}
' inp < ref.txt
while IFS= read -r a
do
grep -m1 -F -- "$a" inp || echo "$a 10 20"
done < ref.txt
결과:
Doc_A 123 abc
Doc_B 123 abc
Doc_C 123 abc
Doc_D 10 20
Doc_E 10 20
Doc_F 10 20