比较 bash 脚本中的多个文件

比较 bash 脚本中的多个文件

bash 和 shell 编程对我来说是新的。我有一些带有扩展名的文件.v.gz,在 bash 命令中我正在执行一些操作,并将结果存储在相同的文件名中 。TXT扩大。

举个例子。TXT文件数据如下所示,我正在考虑4个具有不同文件名和相同扩展名的文件(也许文件也会有30+)

文件_one.txt

statement_modeule_name_1 
statement_modeule_name_2
statement_modeule_name_3
statement_modeule_name_4
statement_modeule_name_5

获取数据.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

数据_新建.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

$ 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

将所有数据连接到一个流中,但为每一行添加文件名前缀。假设数据中没有制表符,我们可以使用制表符作为文件名和原始数据之间的分隔符。然后按第二个制表符分隔字段对数据进行分组,并将文件名折叠到每个组的逗号分隔列表中。

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

给定问题中数据的输出(可以通过传递eg来反转字段的顺序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

或者,使用 Miller ( mlr) 代替 GNU 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

ps:该解决方案有点多余,因为它会比较file1andfile2和 laterfile2以及file1...

输出您的数据:

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这里的另一个主题:两个文件之间的公共行

相关内容