Bashスクリプトで複数のファイルを比較する

Bashスクリプトで複数のファイルを比較する

bashとシェルプログラミングは私にとって新しいものです。拡張子を持つファイルがいくつかあります。.v.gz、bashコマンドでいくつかの操作を実行し、結果を同じファイル名に保存します。 。 txt拡張する。

例えば。 txtファイルデータは以下の通りです。ファイル名が異なり、拡張子が同じ4つのファイルを検討しています(おそらく30以上のファイルがある可能性があります)。

file_one.txt

statement_modeule_name_1 
statement_modeule_name_2
statement_modeule_name_3
statement_modeule_name_4
statement_modeule_name_5

data.txtのインポート

statement_modeule_name_6
statement_modeule_name_7
statement_modeule_name_2
statement_modeule_name_8
statement_modeule_name_9

ファイル.txt

statement_modeule_name_10
statement_modeule_name_11
statement_modeule_name_6
statement_modeule_name_4
statement_modeule_name_14

data_new.txt

statement_modeule_name_15
statement_modeule_name_16
statement_modeule_name_11
statement_modeule_name_5
statement_modeule_name_17

コマンドプロンプトで予想​​されるコード出力

file_one and Fetch_Data   statement_modeule_name_2

Fetch_Data and one_file   statement_modeule_name_6

file_one and Fetch_Data   statement_modeule_name_4

file_one and Fetch_Data and file4    statement_modeule_name_5

Fetch_Data and Data_new   statement_modeule_name_11

私がやっているコードは

for file in *.v.gz;
do
  zgrep -A1 "^module" "$file" | sed -n -e 's/^\(module \)*\(.*(.*)\).*$/\2/p' | cut -f1 -d"(" > $(basename "$file" .v.gz).txt
done     #the result what I get here I mentioned in the question .txt files with data (example)

誰でもこれを行うのに役立ちますか? pythonまたはbashスクリプトを使用できます(bashの場合はpython拡張を削除する必要があります)。

  • 最初のステップで、.txt形式で複数の出力ファイルを生成します。
  • これで、複数の.txtファイルを1行ずつ比較し、予想される出力と同じファイル名を持つファイルに同じ行がある場合は返したいと思います。

答え1

$ FILES=( $(find -maxdepth 1 -type f -printf "%P\n") )

$ cat ${FILES[@]} | 
sort |
uniq -d |
xargs -r -d '\n' -I{} bash -c '
  echo $(sed "s/ / and /g" <<<$(grep -xl "{}" '"${FILES[*]}"')), {}'

結果:

file3.txt and file4.txt, modeule_name_11
file1.txt and file2.txt, modeule_name_2
file1.txt and file3.txt, modeule_name_4
file1.txt and file3.txt and file4.txt, modeule_name_5
file2.txt and file3.txt, modeule_name_6

説明する:

  • FILES=( $(find -maxdepth 1 -type f -printf "%P\n") )-$FILESファイルリストを保持する配列になります。
  • cat ${FILES[@]}- ファイルの内容を印刷します。
  • sort | uniq -d- 他のファイルに表示されない行を確認する必要がないため、重複した行(つまり、複数のファイルに表示される行)のみを表示します。
  • xargs -r -d '\n' -I{} bash -c '- 各行に対して次のスクリプトを実行します。区切り文字は新しい行なので、特殊文字をサポートできます。{}私たちが探している行に置き換えられます
  • grep -xl "{}" '"${FILES[*]}"'-l- 各行に対して、行全体(-x)に一致するファイル()を印刷します。
  • sed "s/ / and /g" <<<$(grep ... ))- 一致するファイル間のスペースを次に置き換えます。「そして」
  • echo $(...), {}- 一致する項目のリストを印刷し、その後に一致する行({})を表示します。

答え2

すべてのデータを1つのストリームにリンクしますが、各行の前にファイル名を付けます。データにタブ文字がないと仮定すると、タブ文字をファイル名と元のデータの間の区切り文字として使用できます。その後、データはタブ区切りの2番目のフィールドにグループ化され、ファイル名は各グループのカンマ区切りリストに縮小されます。

awk -v OFS='\t' '{ print FILENAME, $0 }' *.txt |
datamash --sort groupby 2 collapse 1

特定の質問のデータ出力(たとえば、フィールドの順序を変更できますdatamash cut 2,1):

statement_modeule_name_1        file_one.txt
statement_modeule_name_10       onefile.txt
statement_modeule_name_11       Data_New.txt,onefile.txt
statement_modeule_name_14       onefile.txt
statement_modeule_name_15       Data_New.txt
statement_modeule_name_16       Data_New.txt
statement_modeule_name_17       Data_New.txt
statement_modeule_name_2        Fetch_Data.txt,file_one.txt
statement_modeule_name_3        file_one.txt
statement_modeule_name_4        file_one.txt,onefile.txt
statement_modeule_name_5        Data_New.txt,file_one.txt
statement_modeule_name_6        Fetch_Data.txt,onefile.txt
statement_modeule_name_7        Fetch_Data.txt
statement_modeule_name_8        Fetch_Data.txt
statement_modeule_name_9        Fetch_Data.txt

または、mlrGNUの代わりにMiller()を使用してくださいdatamash

awk -v OFS='\t' '{ print FILENAME, $0 }' *.txt | 
mlr --tsv -N nest --ivar , -f 1

質問のデータ出力を提供します。

Data_New.txt    statement_modeule_name_15
Data_New.txt    statement_modeule_name_16
Data_New.txt,onefile.txt        statement_modeule_name_11
Data_New.txt,file_one.txt       statement_modeule_name_5
Data_New.txt    statement_modeule_name_17
Fetch_Data.txt,onefile.txt      statement_modeule_name_6
Fetch_Data.txt  statement_modeule_name_7
Fetch_Data.txt,file_one.txt     statement_modeule_name_2
Fetch_Data.txt  statement_modeule_name_8
Fetch_Data.txt  statement_modeule_name_9
file_one.txt    statement_modeule_name_1
file_one.txt    statement_modeule_name_3
file_one.txt,onefile.txt        statement_modeule_name_4
onefile.txt     statement_modeule_name_10
onefile.txt     statement_modeule_name_14

答え3

commあなたの友達です。両方のファイルについて:

$ comm -12 <(sort file_one.txt) <(sort Fetch_Data.txt)
statement_modeule_name_2

txt現在のディレクトリ内のすべてのファイルについて:

for FILE1 in *.txt; do
  for FILE2 in *.txt; do
    [ "$FILE1" == "$FILE2" ] && continue
    echo "$FILE1  $FILE2  $(comm -12 <(sort $FILE1) <(sort $FILE2))"
  done
done

file1ps:このソリューションはandとfile2後で比較するため、少し冗長です。file2file1

データを出力します。

Data_New.txt  Fetch_Data.txt  
Data_New.txt  file_one.txt  statement_modeule_name_5
Data_New.txt  onefile.txt  statement_modeule_name_11
Fetch_Data.txt  Data_New.txt  
Fetch_Data.txt  file_one.txt  statement_modeule_name_2
Fetch_Data.txt  onefile.txt  statement_modeule_name_6
file_one.txt  Data_New.txt  statement_modeule_name_5
file_one.txt  Fetch_Data.txt  statement_modeule_name_2
file_one.txt  onefile.txt  statement_modeule_name_4
onefile.txt  Data_New.txt  statement_modeule_name_11
onefile.txt  Fetch_Data.txt  statement_modeule_name_6
onefile.txt  file_one.txt  statement_modeule_name_4

commここで別のトピックの詳細をご覧ください。2つのファイル間の共通行

関連情報