파일이 두 개 있어요
문서 1 (참고 문서)
xxx xxxxx 00
xxx xxxxx 01
xxx xxxxx 02
xxx xxxxx 03
xxx xxxxx 04
xxx xxxxx 00
xxx xxxxx 01
xxx xxxxx 02
xxx xxxxx 03
xxx xxxxx 04
파일 2
12345 2021/04/02 00
1212 2021/04/02 01
12123 2021/04/02 02
12123 2021/04/02 04
1223 2021/04/03 01
124 2021/04/03 02
123 2021/04/03 03
각 파일의 마지막 필드를 비교하고 첫 번째 파일(내 참조 파일)에서 누락된 줄을 추가하고 싶습니다.
예를 들어 출력을 원합니다.
12345 2021/04/02 00
1212 2021/04/02 01
12123 2021/04/02 02
xxx xxxxx 03
12123 2021/04/02 04
xxx xxxxx 00
1223 2021/04/03 01
124 2021/04/03 02
123 2021/04/03 03
xxx xxxxx 04
을 사용해 보았 awk -F ' ' 'NR==FNR{a[$2]++;next}a[$2] && $1>=00' test2.txt test1.txt
더니 file1에 누락된 세 번째 값이 추가되었지만 출력에서는 필요한 데이터(두 번째 및 세 번째 필드)도 제거되었습니다.
답변1
어쩌면 이런 게 있지 않을까요?
cat file2 | awk '!(1 in f) {if ((getline l < "-") == 1) split(l, f)} $3!=f[3] {print;next} {print l; delete f}' file1 | column -t
스크립트에서는 다음을 file1
예상합니다.토론file2
그것을 기대하면서 awk표준 입력. 나는 이것을 더 명확하게 하기 위해 "cat의 쓸모없는 사용"을 사용했지만 당연히 < file2
이것을 리디렉션으로 제공할 수 있습니다. 실제로 파일 이름을 스크립트 자체에 포함시킬 수도 있지만 "file2"
이 방법이 좀 더 유연합니다."-"
getline
또한 두 파일은 field3 값과 관련하여 "동기화"되거나 사용 사례에 적합한 경우 "조기 앞서" 시작될 것으로 예상됩니다 file2
.file1
스크립트는 읽기 쉽도록 개별적으로 분류되었으며 자세한 설명은 다음과 같습니다.
# Check if our `real_fields` array is not existent.
# NOTE: we use the `<index> in <array>` construct
# in order to force awk treat `real_fields` name as an
# array (instead of as a scalar as it would by default)
# and build it in an empty state
!(1 in real_fields) {
# get the next line (if any) from the "real" file
if ((getline real_line < "-") == 1)
# split that line in separate fields populating
# our `real_fields` array
split(real_line, real_fields)
# awk split function creates an array with numeric
# indexes for each field found as per FS separator
}
# if field3 of the current line of the "reference"
# file does not match the current line of the "real" file..
$3!=real_fields[3] {
# print current line of "reference" file
print
# go reading next line of "reference" file thus
# skipping the final awk pattern
next
}
# final awk pattern, we get here only if the pattern
# above did not match, i.e. if field3 values from both
# files match
{
# print current line of "real" file
print real_line
# delete our real_fields array, thus triggering
# the fetching of the next line of "real" file as
# performed by the first awk pattern
delete real_fields
}
답변2
배열의 순서를 설정해야 합니다. 그렇지 않으면 awk가 행 순서를 재정렬합니다.
#!/usr/bin/awk -f
BEGIN {
PROCINFO["sorted_in"] = "@ind_str_asc"
}
NR==FNR {
a[i++,$3]=$0
next
}
{
for (c in a) {
split(c, s, SUBSEP)
if (s[2] == $3) {
print $0
getline
} else {
print a[c]
}
}
}
./script.awk file1 file2