네 번째 파일을 기반으로 세 개의 CSV 파일을 업데이트하는 방법

네 번째 파일을 기반으로 세 개의 CSV 파일을 업데이트하는 방법

나는 4개를 갖고 있다데이터 세트파일, 네 번째 파일의 값을 기반으로 세 개의 파일 집합을 업데이트하고 싶습니다.

  1. 파일 1이름이 포함되어 있습니다.
  2. 파일_2디지털 ID.
  3. 파일_3다음의 ID를 포함합니다.파일 1그리고파일_2, 각 ID 조합 쌍에 해당하는 값입니다.
  4. 파일_4새로운 이름의 조합을 포함하는 값입니다.

내가해야 할 일은 추가하는 것입니다파일_4새 이름은파일 1그리고파일_2, 점진적으로 자동으로 ID를 생성합니다. 그런 다음 값을파일_3새로운 ID 조합을 기반으로 합니다. 문제는 간단합니다. 아래 예에서 설명하는 것처럼 문제를 조금 복잡하게 만드는 것은 쉼표로 구분된 하위 필드가 있다는 것입니다."1,2,3"일부에서는데이터 세트에스.

이를 달성하려면 스크립트를 사용해야 하지만 사용하기가 더 쉬울 수도 있습니다.SQL.

파일 1

nid,vname
1,name1
2,name2
3,name3

파일_2

did,dname
1,"s1,s2,s3"
2,s4
3,"s5,s6"

파일_3

nid,did,value
1,1,aa
1,2,gg
1,3,tt
2,1,aa
2,2,ag
2,3,at
3,1,aa
3,2,tt

파일_4

new_name,new_dataset,value
name1,"s7,s8",aa
name2,"s9,s10",gg
name8,"s1,s2,s3",aa

따라서 업데이트된 세 개의 파일은 다음과 같아야 합니다.

File_1_업데이트

nid,vname
1,name1
2,name2
3,name3
4,name8

File_2_업데이트

did,dname
1,"s1,s2,s3"
2,s4
3,"s5,s6"
4,"s7,s8"
5,"s9,s10"

File_3_업데이트

nid,did,value
1,1,aa
1,2,gg
1,3,tt
1,4,aa
2,1,aa
2,2,ag
2,3,at
2,5,gg
3,1,aa
3,2,tt
4,1,aa

답변1

데이터가 게시한 것과 정확히 같다고 가정하면 일반 bash에서 다음을 수행할 수 있습니다. (경고하다: 파일을 제자리에서 수정합니다. 테스트 전 백업을 꼭 해주시기 바랍니다. )

처음 두 파일을 관리하는 여러 기능:

next_id() {
  file="$1"
  # assumes file is sorted by id
  echo $(( $(tail -n 1 $file|cut -d, -f1) + 1 ))
}

가설파일 1그리고파일 2id 열을 기준으로 정렬하면 마지막 행의 첫 번째 부분을 가져와서 1씩 증가시켜 다음 ID를 생성합니다.

find_or_create_id() {
  file="$1"
  item="$2"
  # check if we already have that item
  id=$(grep -m 1 ",$item$" "$file" 2> /dev/null)
  if [[ $? -ne 0 ]] ; then
    # generate the next id, append
    id=$(next_id "$file")
    echo "$id,$item" >> "$file"
  else
    # got it already
    id=${id/,*}
  fi
  echo "$id"
}

처음 두 파일 중 하나에서 항목(vname 또는 dname)을 찾습니다. 발견되면 기존 ID가 반환됩니다. 그렇지 않은 경우 다음 ID를 생성하여 파일에 다시 저장하십시오.

올바른 하위 문자열이 있으면 주요 부분은 매우 간단합니다.

while read line ; do
  col1=${line/,*}  # everything up to first ,
  col3=${line//*,} # everything after last ,
  col2=${line%,*}  # everything after first ,
  col2=${col2#*,}  # everything before last ,
  id1=$(find_or_create_id file1 "$col1")
  id2=$(find_or_create_id file2 "$col2")
  # don't insert duplicates
  if ! grep -m 1 -q "^$id1,$id2," file3 ; then
    echo "$id1,$id2,$col3" >> file3
  fi
done < <(tail -n +2 file4)

이것은 것이다아니요마지막 파일을 순서대로 삽입하면 끝에 새 줄이 추가됩니다.


즉, 이러한 파일 중 크기가 큰 경우 데이터베이스가 적합할 것입니다. 데이터베이스 서버가 필요하지 않다면 SQLite를 고려해보세요.

순차 ID에 신경 쓰지 않고(단순히 다르다는 점만) integer primary key autoincrement테이블 1과 테이블 2에 ID(vname 및 dname의 고유 키 포함)를 추가했다고 가정하면 업데이트는 다음과 같습니다(아마도 이 방법보다 더 나을 것입니다). 좀 더 미묘한 접근 방식 insert or ignore):

insert or ignore into tab1(vname) select distinct vname from tab4;
insert or ignore into tab2(dname) select distinct dname from tab4;

insert or ignore into tab3(id1,id2,value)
  select tab1.id, tab2.id, tab4.value
  from tab4
  left join tab1 on tab1.vname = tab4.vname
  left join tab2 on tab2.dname = tab4.dname;

SQLite "는 .

.separator ,
.import fileX tabX

적어도 현재 가지고 있는 샘플에 대해서는 Right Thing™을 수행하십시오.

간단한 아키텍처:

create table tab1 (id integer primary key autoincrement, vname text);
create unique index tab1_vname on tab1(vname);

create table tab2 (id integer primary key autoincrement, dname text);
create unique index tab2_dname on tab2(dname);

create table tab3 (id1 int, id2 int, value text,
                   constraint tab3_pk primary key(id1, id2));

create table tab4 (vname text, dname text, value text);

답변2

이것은2/3답, 활용*닉스소프트웨어 도구. File_1_업데이트:

head -n 1 file_1 ; \
{ tail -n +2 file_1 | cut -d ',' -f 2 ; \
  tail -n +2 file_4 | cut -d ',' -f 1 ; } | \
sort -n | uniq | nl -s ',' | tr -d ' '

산출:

nid,vname
1,name1
2,name2
3,name3
4,name8

File_2_업데이트:

head -n 1 file_2 ; \
{ tail -n +2 file_2 | cut -d ',' -f 2- ; \
  tail -n +2 file_4 | cut -d ',' -f 2- | \
  rev | cut -d ',' -f 2- | rev ; } | \
sort -n | uniq | nl -s ',' | tr -d ' '

산출:

did,dname
1,"s1,s2,s3"
2,s4
3,"s5,s6"
4,"s7,s8"
5,"s9,s10"

관련 정보