필드가 다음과 같은 파일이 있습니다.ID,지정하다,부모 ID, 그리고부모 지정. 파일의 내용은 다음과 같습니다.
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1
b1 Sr.R&D B1
b2 Jr.SR&D B1
a2 Jr.Sales A1
B1 M.D-R&D 0 UmbrellaCorp
난 갖길 원해부모 지정네 번째 열이 누락된 행의 경우 이는 기본적으로 다음을 의미합니다.
- 각 줄을 읽으십시오
- 얻다부모 ID세 번째 열부터 시작
- 첫 번째 열의 값과 일치시키세요.
- 자식 앞의 네 번째 열 4에 삽입하십시오.
결과는 아래와 같습니다.
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
Excel을 사용하여 동일한 작업을 수행하는 방법을 알고 있지만 vlookup
스크립트를 사용해야 합니다.
답변1
최종 답변은 더 많은 설명과 함께 아래에 제공되며 관련 예제 입력/출력으로 업데이트되었습니다.
누락된 값을 채우는 것이 awk에서 2단계 접근 방식을 수행하는 것보다 더 효율적이고 메모리를 덜 사용하도록 데이터를 먼저 정렬하며, 가독성을 위해 최종 출력이 입력보다 더 잘 구성됩니다.
$ cat tst.sh
#!/usr/bin/env bash
awk '
BEGIN { FS=OFS="\t" }
{ print (NR>1), ($4=="" ? $3 : $1), $4, $1, NR, $0 }
' "${@:--}" |
sort -t$'\t' -k1,1n -k2,2 -k3,3r -k4,4 -k5,5n |
cut -f6- |
awk '
BEGIN { FS=OFS="\t" }
$4 != "" { d = $2 }
$4 == "" { $4 = d }
{ print }
'
$ ./tst.sh file | column -s$'\t' -t
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D
awk에 대한 첫 번째 호출은 다음과 같이 정렬될 수 있도록 입력을 수정합니다.
(NR>1)
= 정렬 후 헤더 행이 먼저 남아 있는지 확인하기 위한 헤더 여부 0 또는 1 표시기,($4=="" ? $3 : $1)
= 관련 행을 그룹화하는 데 사용되는 각 행의 ID 또는 ParentID$4
= ParentDesignation - ParentDesignation이 있는 행이 동일한 ID/ParentID를 갖지 않는 행 앞에 오도록 정렬할 수 있습니다.$1
= ID, 따라서 ID별로 알파벳순으로 하위 항목을 정렬할 수 있습니다.NR
= 따라서 다른 모든 것이 공통적이라면 입력에 나타나는 순서대로 행을 인쇄할 수 있습니다(이 경우에는 각 ID가 고유한 것처럼 보이므로 필요하지 않지만 다른 유사한 경우에는 괜찮을 것입니다).
sort
그런 다음 위의 필드를 전달한 다음 삭제 데코레이터를 사용하여 실제로 채우는 최종 스크립트에 전달합니다 .cut
awk
$4
이러한 단계가 어떤 역할을 하는지 확실하지 않은 경우 각 단계를 |
한 번에 하나씩 변경하면 각 단계에서 어떤 일이 일어나는지 확인할 수 있습니다.| cat; exit
이전 답변:
아래 설명을 보면 부모(존재하는 경우)가 데이터에서 항상 자식 앞에 나타난다고 가정하면 이것이 아마도 원하는 것일 것입니다.
$ cat tst.awk
BEGIN { FS=OFS="\t" }
$4 != "" {
id2des[$1] = $2
}
$4 == "" {
$4 = id2des[$3]
}
{ print }
$ awk -f tst.awk file
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D
원래 답변:
모든 정보가 포함된 상위 행과 $4가 누락된 하위 행이 있는 것처럼 보이기 때문에 문제는 실제로 지정한 것보다 더 단순해 보입니다. 이 경우 아무것도 찾을 필요가 없습니다. 필요한 것은 다음과 같습니다. :
$ awk 'BEGIN{FS=OFS="\t"} $4!=""{d=$2} $4==""{$4=d} 1' file
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D
$ awk 'BEGIN{FS=OFS="\t"} $4!=""{d=$2} $4==""{$4=d} 1' file | column -s$'\t' -t
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D
답변2
항상 자식앞에 부모가 있었다면...
awk -F"\t" -v OFS="\t" '
{dad[$1]=$2}
!$4{$4=dad[$3]}1
' file
그렇지 않다면 두 번 실행하십시오 ...
awk -F"\t" -v OFS="\t" '
NR==FNR{dad[$1]=$2;next}
!$4{$4=dad[$3]}1
' file file
답변3
또 다른 매우 유사한 솔루션: 수직 대칭을 사용하려고 입력 파일에 두 번 액세스하는 (gnu)awk 여러 줄 스크립트입니다. $ cat awklookup
#!/usr/bin/awk -f
BEGIN{FS=OFS="\t";
ARGC=3; ARGV[2] = ARGV[1]} ## visit the input file twice
ARGIND==1 { tab[$1]=$2 }
ARGIND==2 && !$4 { $4=tab[$3] }
ARGIND==2 { print }
그 다음에:
$ chmod 755 awklookup
$ ./awklookup infile
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D