ksh88 AIX는 하나의 열에서 부분 문자열 일치를 기반으로 두 파일을 병합합니다.

ksh88 AIX는 하나의 열에서 부분 문자열 일치를 기반으로 두 파일을 병합합니다.

AIX 시스템에서 ksh88을 사용하여 많은 것을 시도했지만 아무 것도 작동하지 않았습니다.

File_A헤더가 없는 2개의 열이 있습니다. 열 1에는 디렉터리를 생성한 사용자 그룹, 열 2에는 전체 파일 경로가 있습니다. 예를 들면 다음과 같습니다.

Userwh0c4r35     /fake/file/path/directory_name
User1234567      /another/file/path/different_dir
User0987654      /some/other/path/another_name

File_B2개의 열이 있고 헤더는 없습니다. 열 1에는 디렉터리 크기(MB), 열 2에는 디렉터리의 부분 경로 이름이 있습니다. 예를 들면 다음과 같습니다.

2183.31     directory_name
1750.09     directory_name/subfolder
1028.14     directory_name/subfolder/sub_subfolder
3658.97     different_dir
2159.62     different_dir/subfolder
1001.01     different_dir/different_subfolder 

등.

문제는 File_B(즉, directory_name, directory_name/subfolder, , ...) directory_name/subfolder/sub_subfolder에 중복된 디렉터리 이름이 있다는 것입니다.

내가 원하는 것은 파일에서 다음과 같은 출력입니다(솔직히 열의 순서는 신경 쓰지 않고 열이 모두 존재한다는 것뿐입니다).

Userwh0c4r35     /fake/file/path/directory_name     2183.31
User1234567      /another/file/path/different_dir   3658.97

이것은 충분히 간단해 보이지만 나는 그것을 알아낼 수 없었습니다. 내가 얻을 수 있는 가장 가까운 방법은 부분적으로 일치하는 두 파일에서 사용자 그룹, 전체 경로 이름 및 줄 번호를 가져오는 것입니다. 그러나 디렉터리 크기(열 1 File_B) 는 가져올 수 없습니다 .

저를 너무 가까워졌지만 아직 거기에 도달하지 못한 코드는 다음과 같습니다(SO 및 다양한 온라인 튜토리얼에서 함께 엮음).

awk '
NR==FNR {
    a[$2]=$1
    next
}
{
    for(i in a) 
        if($2 ~ i) 
            {print $2,a[$2],$1} 
}' file_B file_A 

File_A의 열 2가 File_A부분적으로 의 열 2와 일치하는 각 행에 중복 항목이 있는 목록을 생성합니다 File_B. 예를 들면 다음과 같습니다.

Userwh0c4r35     /fake/file/path/directory_name
Userwh0c4r35     /fake/file/path/directory_name
Userwh0c4r35     /fake/file/path/directory_name

directory_name( directory_name/subfolder, , 및 각각 1개 directory_name/subfolder/sub_subfolder)

print제가 생각할 수 있는 모든 것을 시도해 보았 으나 소용이 없었습니다... NR,FNR,i,$0,a[$NR],a[$FNR],a[$1],a[$2],$1,$2저도 사용해 보았지만 printf역시 효과가 없었습니다...

답변1

당신이 원하는 것은 본질적으로 두 개의 데이터베이스 테이블을 조인하는 것입니다. 편리하게도 이 작업을 수행하는 적절한 이름의 명령이 있습니다 join.

여기서는 필요하지 않습니다 awk. 저는 AIX도 AIX도 없습니다 ksh88. 이것은 Linux의 Bash이지만 빠르게 확인했습니다.AIX 매뉴얼그리고 그것이 효과가 있어야 한다고 생각했습니다.

저는 다음과 같은 테스트 환경을 준비했습니다.

$ cat filea
Userwh0c4r35     /fake/file/path/directory_name5
Userwh0c4r36     /fake/file/path/directory_name6
Userwh0c4r37     /fake/file/path/directory_name7
$ cat fileb
1234    directory_name5
2345    directory_name6
3456    directory_name7

1 단계filea: 디렉토리 경로 이름의 마지막 부분만 포함하는 열을 추가합니다 .

$ sed 's|\(.*\)/\(.*\)|\1/\2 \2|' filea > filea.tmp
$ cat filea.tmp
Userwh0c4r35     /fake/file/path/directory_name5 directory_name5
Userwh0c4r36     /fake/file/path/directory_name6  directory_name6
Userwh0c4r37     /fake/file/path/directory_name7  directory_name7

2 단계: 두 파일을 디렉토리 이름별로 정렬합니다(이 점을 지적한 Mark Plotnick에게 감사드립니다).

$ sort -k3 filea.tmp > filea.tojoin
$ sort -k2 fileb > fileb.tojoin

3단계: AND를 사용하여 열 3( ) 및 열 2( )의 디렉터리 이름을 기준으로 join조인합니다 .filebfileafileb

$ join -1 3 -2 2 filea.tojoin fileb.tojoin > result
$ cat result
directory_name5 Userwh0c4r35 /fake/file/path/directory_name5 1234
directory_name6 Userwh0c4r36 /fake/file/path/directory_name6  2345
directory_name7 Userwh0c4r37 /fake/file/path/directory_name7  3456

선택적 4단계: cutA는 원하지 않는 경우 첫 번째 열을 삭제합니다.

답변2

무엇을 하려는지 명확하지 않으며 예제 입력/출력은 현재 테스트에 유용하지 않지만 다음은 추측입니다.

$ cat tst.awk
BEGIN { OFS="\t" }
{
    val = $1                                    # val = Userwh0c4r35 or 2183.31
    sub(/^[^[:space:]]+[[:space:]]+/,"")        # Allows spaces in directory names vs using $2
    dir = $0                                    # dir = /fake/file/path/directory_name or directory_name/subfolder
}
NR==FNR {
    sub(".*/","",dir)                           # dir = directory_name
    dir2path[dir] = $0
    dir2grp[dir]  = val
    next
}
{
    sub("/.*","",dir)                           # dir = directory_name
    print dir2grp[dir], dir2path[dir], val
}

$ awk -f tst.awk File_A File_B
Userwh0c4r35    /fake/file/path/directory_name  2183.31
Userwh0c4r35    /fake/file/path/directory_name  12345
Userwh0c4r35    /fake/file/path/directory_name  9876

위의 내용은 File_A의 다른 경로(예: 및 ) directory_name끝에 동일한 콘텐츠가 나타날 수 없다고 가정 하고 다음 입력 파일에서 실행됩니다./foo/directory_name/bar/directory_name

$ head File_*
==> File_A <==
Userwh0c4r35     /fake/file/path/directory_name

==> File_B <==
2183.31     directory_name
12345       directory_name/subfolder
9876        directory_name/subfolder/sub_subfolder

디렉터리 이름에 탭 문자가 포함될 수 있는 경우 다른 출력 형식을 사용해야 합니다. 개행 문자를 포함할 수 있는 경우 다른 입력 형식도 필요합니다.

관련 정보