私は4つを持っていますデータセットファイル、4番目のファイルの値に基づいて3つのファイルセットを更新したいと思います。
- ファイル1名前が含まれています。
- ファイル_2デジタルID。
- ファイル_3次のIDが含まれています。ファイル1そしてファイル_2, 各 ID 組合せペアに対応する値です。
- ファイル_4新しい名前の組み合わせを含む値です。
私がしなければならないことは追加することですファイル_4新しい名前はファイル1そしてファイル_2、徐々に自動的にIDを生成します。その後、ファイル_3新しいIDの組み合わせに基づいています。問題は簡単です。以下の例で説明するように、問題を少し複雑にするのは、カンマ区切りのサブフィールドがあることです。「1,2,3」一部ではデータセットS.
これを達成するにはスクリプトを使用する必要がありますが、使いやすくなる可能性があります。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
したがって、更新された3つのファイルは次のようになります。
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で次のことができます。 (警告する:ファイルを所定の位置に変更します。テスト前のバックアップを必ずお試しください。 )
最初の2つのファイルを管理するいくつかの機能:
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"
}
最初の2つのファイルのいずれかでエントリ(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"