Bash를 사용하여 열 기반 텍스트 파일을 트리 구조로 형식 지정

Bash를 사용하여 열 기반 텍스트 파일을 트리 구조로 형식 지정

이를 변경할 수 있는 Unix/Linux 명령이 있습니까?

AMERICA USA NEW_YORK    AB-100
AMERICA USA NEW_YORK    VF-200
AMERICA USA NEW_YORK    XY-243
AMERICA USA LOS_ANGELES UH-198
AMERICA CANADA  TORONTO UT-876
AMERICA CANADA  TORONTO UT-877
AMERICA CANADA  VANCOUVER   UT-871
AMERICA CANADA  VANCOUVER   UT-872
AMERICA CANADA  VANCOUVER   UT-873
AMERICA MEXICO  MEXICO  OU-098
AMERICA MEXICO  MONTERREY   OU-099
AMERICA MEXICO  MONTERREY   OU-100
EUROPE  FRANCE  PARIS   IV-122
EUROPE  FRANCE  PARIS   AV-112
EUROPE  FRANCE  PARIS   IF-111
EUROPE  FRANCE  PARIS   XX-190
EUROPE  FRANCE  TOULOUSE    TL-654

다음을 입력하세요:

AMERICA
    USA
        NEW_YORK
            AB-100
            VF-200
            XY-243
        LOS_ANGELES
            UH-198
    CANADA  
        TORONTO 
            UT-876
            UT-877
        VANCOUVER
            UT-871
            UT-872
            UT-873
    MEXICO  
        MEXICO  
            OU-098
        MONTERREY
            OU-099
            OU-100
EUROPE
    FRANCE
        PARIS
            IV-122
            AV-112
            IF-111
            XX-190
        TOULOUSE
            TL-654

답변1

귀하의 예를 들어:

dir=$(mktemp -d)
sed 's|\t|/|g' file | while read -r line; do mkdir -p "$dir/$line"; done
(cd "$dir"; tree)
rm -r "$dir"

산출:

.
미국
│ ├── 캐나다
│ │ ├── 토론토
│ │ │ ├── UT-876
│ │ │ └── UT-877
│ │ └── 밴쿠버
│ │ ├── UT-871
│ │ ├── UT-872
│ │ └── UT-873
│ ├── 멕시코
│ │ ├── 멕시코
│ │ │ └── OU-098
│ │ └── 몬트레이
│ │ ├── OU-099
│ │ └── OU-100
미국
│ ├── LOS_ANGELES
│ │ └── UH-198
│ └── 뉴욕
│ ├── AB-100
│ ├── VF-200
│ └── XY-243
└── 유럽
    └── 프랑스
        ├── 파리
        │ ├── AV-112
        │ ├── IF-111
        │ ├── IV-122
        │ └── XX-190
        └── 툴루즈
            └── TL-654

답변2

awk표준을 사용하고 awk행의 원래 순서를 유지하며 데이터의 열 수를 제한 없이 사용하는 스크립트 :

awk -F $'\t' '
  function indent (n, i) { for (i=1; i<=n; i++) printf "\t" }

  { for (i=1; i<=NF; i++)
        if ($i != o[i]) {
            printf "%s%s\n", indent(i-1), $i
            o[i] = $i
        }
  }
'


동일한 프로그램 논리를 셸에서 구현할 수 있습니다. 을 위한 bash:

indent () { ind=$( printf "%*s" "$1" '' ) ; printf "${ind// /$'\t'}" ;}

while IFS=$'\t' read -a f
do
    for ((i=0; i<${#f}; i++))
    do
        if [[ "${f[i]}" != "${o[i]}" ]]
        then
            printf "%s%s\n" "$( indent "$i" )" "${f[i]}"
            o[i]=${f[i]}
        fi
    done
done

참고: 조정 ksh해야 하기 때문입니다 .read -aread -A

답변3

에서는 awk다음을 수행할 수 있습니다.

$ awk '{
        a[$1][$2][$3] ? 
            a[$1][$2][$3]=a[$1][$2][$3]"\n\t\t\t"$4 :
            a[$1][$2][$3]="\t\t\t"$4 ;
      }
      END{
        for(cont in a){
            printf "%s\n", cont;
            for(count in a[cont]){
                printf "\t%s\n", count;
                for(city in a[cont][count]){
                    print "\t\t"city"\n"a[cont][count][city]
      }}}}' file
EUROPE
    FRANCE
        TOULOUSE
            TL-654
        PARIS
            IV-122
            AV-112
            IF-111
            XX-190
AMERICA
    USA
        NEW_YORK
            AB-100
            VF-200
            XY-243
        LOS_ANGELES
            UH-198
    CANADA
        VANCOUVER
            UT-871
            UT-872
            UT-873
        TORONTO
            UT-876
            UT-877
    MEXICO
        MEXICO
            OU-098
        MONTERREY
            OU-099
            OU-100

펄에서는:

perl -lane 'push @{$k{$F[0]}{$F[1]}{$F[2]}},"\t\t\t".$F[3];
            END{
                for $cont (keys(%k)){
                    print "$cont";
                    for $coun (keys(%{$k{$cont}})){
                        print "\t$coun";
                        for $city (keys(%{$k{$cont}{$coun}})){
                            print "\t\t$city\n", 
                              join "\n",@{$k{$cont}{$coun}{$city}}
             }}}}' file
EUROPE
    FRANCE
        PARIS
            XX-190
            XX-190
        TOULOUSE

            TL-654
AMERICA
    USA
        NEW_YORK
            XY-243
            XY-243
        LOS_ANGELES

            UH-198
    MEXICO
        MONTERREY
            OU-100
            OU-100
        MEXICO

            OU-098
    CANADA
        VANCOUVER
            UT-873
            UT-873
        TORONTO
            UT-877
            UT-877

관련 정보