나는 이것을 사용하여 paste
세 개의 텍스트 파일(정렬할 필요가 없음)을 세 개의 열이 있는 하나의 문서로 병합합니다.
paste a.txt b.txt c.txt
나는 열에 공통된 요소가 일치하지 않는 요소(현재는 그렇습니다)와 공유하지 않고 동일한 행을 차지하기를 원합니다. 마찬가지로 고유 요소에는 자체 행이 있어야 합니다. 각 열의 요소는 원래 순서를 유지해야 합니다.
이것은 간단한 예입니다.
입력하다
1 1 1
2 2 2
3 4 4
5 5 5
1 1 2
3 3 3
원하는 출력
1 1 1
2 2 2
3
4 4
5 5 5
1 1
2
3 3 3
다음은 더 복잡한 예입니다.
입력하다
000 000 000
002 002 001
006 006 006
008 008 007
009 009 009
011 012 010
013 013 013
015 015 014
016 016 016
018 019 017
020 020 020
021 021 022
024 024 024
026 025 025
028 026 026
118 028 027
119 118 118
032 119 117
036 032 032
037 033 033
039 034 034
040 037 037
042 039 038
043 040 040
045 042 041
046 043 043
048 045 044
046 046
049 047
원하는 출력
000 000 000
001
002 002
006 006 006
007
008 008
009 009 009
010
011
012
013 013 013
014
015 015
016 016 016
017
018
019
020 020 020
021 021
022
024 024 024
025 025
026 026 026
027
028 028
118 118 118
117
119 119
032 032 032
033 033
034 034
036
037 037 037
038
039 039
040 040 040
041
042 042
043 043 043
044
045 045
046 046 046
047
048
049
이상적으로는 Linux/Unix에 내장된 도구를 사용하고 싶습니다. 또한 출력을 세 개의 열이 있는 단일 문서로 유지하고 싶습니다(예: > whatever.csv
.
내가 얻을 수 있는 가장 가까운 것은 sdiff
원본 텍스트 파일에서 실행되는 것이었지만 파일에서 함께 공유된 요소가 올바르게 정렬되었지만 내가 원하는 방식으로 차이점을 처리하지 못했습니다.
답변1
BEGIN {
# We assume the default input field separator (changeable with "-F")
# Output will be tab delimited.
OFS = "\t"
}
{
# The number of output records that this input record results in.
k=0
# "seen" records which new record a field should be part of.
# There may be NF new records for each input record if all
# fields are unique.
delete seen
# "a" holds all data for the new output records.
# It's basically a 2-dimensional NFxNF matrix
# encodod in a 1-dimensional array.
delete a
# Iterate over the fields
for (i=1; i<=NF; ++i) {
if (!seen[$i]) {
# This data has not been seen before (in this input record),
# assign it to the next output line.
seen[$i] = ++k
}
# Assign the input field to the right spot
a[(seen[$i]-1)*NF + i] = $i
}
# Save NF as this is reset by emptying $0 later.
nf = NF
# Create and output new lines
for (j = 1; j<=k; ++j) {
$0 = ""
# Create new output record
for (i = 1; i<=nf; ++i)
$i = a[(j-1)*nf + i]
# Output record
print
}
}
주어진 데이터에 대해 테스트:
$ awk -f script.awk file
1 1 1
2 2 2
3
4 4
5 5 5
1 1
2
3 3 3
다른 데이터에 대한 테스트:
$ cat file
a b c e
1 2 1 1
2 1 1 1
1 1 1 2
$ awk -f script.awk file
a
b
c
e
1 1 1
2
2
1 1 1
1 1 1
2
답변2
paste
이것은 쉘 스크립트에서 및 를 사용하는 "무차별 대입" 솔루션입니다 read
.
#!/bin/sh
paste a.txt b.txt c.txt |
while read -r a b c; do
if [ "$a" = "$b" ] && [ "$b" = "$c" ]; then
printf '%s\t%s\t%s\n' "$a" "$b" "$c"
elif [ "$a" = "$b" ]; then
printf '%s\t%s\n\t\t%s\n' "$a" "$b" "$c"
elif [ "$a" = "$c" ]; then
printf '%s\t\t%s\n\t%s\n' "$a" "$c" "$b"
elif [ "$b" = "$c" ]; then
printf '%s\n\t%s\t%s\n' "$a" "$b" "$c"
else
printf '%s\n\t%s\n\t\t%s\n' "$a" "$b" "$c"
fi
done
더 우아한 해결책이 있을 수 있지만 즉시 좋은 해결책이 생각나지 않습니다.
원한다면 이를 사용할 수 있습니다 awk
. 결과는 매우 유사해 보일 것입니다. (사용의 한 가지 장점은 유용하다면 작업을 동시에 수행한다는 awk
것입니다 .)paste