Extraire les mêmes lignes de deux fichiers sans tenir compte des majuscules / minuscules

L’objective est d’extraire les mêmes lignes à partir de deux fichiers sans tenir compte des majuscules / minuscules et sans tenir compte des ponctuations

J’ai deux fichiers

source.txt

 Foo bar blah blah black sheep Hello World Kick the, bucket 

processed.txt

 foo bar blah sheep black Hello world kick the bucket , 

Sortie souhaitée (à partir de source.txt ):

 Foo bar Hello World Kick the, bucket 

Je l’ai fait en tant que tel:

 from ssortingng import punctuation with open('source.txt', 'r') as f1, open('processed.txt', 'r') as f2: for i,j in zip(f1, f2): lower_depunct_f1 = " ".join("".join([ch.lower() for ch in f1 if f1 not in punctuation]).split()) lower_depunct_f2 = " ".join("".join([ch.lower() for ch in f2 if f2 not in punctuation]).split()) if lower_depunct_f1 == lower_depunct_f2: print f1 else: print 

Est-il possible de faire cela avec les outils bash ? perl, shell, awk, sed?

Plus facile à faire en utilisant awk :

 awk 'FNR==NR {s=toupper($0); gsub(/[[:blank:][:punct:]]+/, "", s); a[s]++;next} {s=toupper($0); gsub(/[[:blank:][:punct:]]+/, "", s); print (s in a)?$0:""}' file2 file1 Foo bar Hello World Kick the, bucket 

La solution Perl est assez similaire à celle de Python:

 open my $S1, '<', 'source.txt' or die $!; open my $S2, '<', 'processed.txt' or die $!; while (defined(my $s1 = <$S1>) and defined (my $s2 = <$S2>)) { s/[[:punct:]]//g for $s1, $s2; $_ = lc for $s1, $s2; print $s1 eq $s2 ? $s1 : "\n"; } 

Notez que le résultat est différent du vôtre, car l’espace après le kick the bucket de kick the bucket n’a pas été supprimé.

Solution Bash, tout à fait identique à celle de Perl, avec le même résultat différent (car l’espace après le kick the bucket n’a pas été supprimé):

 #!/bin/bash shopt -s nocasematch exec 3<> source.txt # Open source.txt and assign fd 3 to it. exec 4<> processed.txt while read <&3 varline && read <&4 varpro do varline_noPunct=`echo $varline | tr -d '[:punct:]'` varpro_noPunct=`echo $varpro | tr -d '[:punct:]'` [[ $varline_noPunct == $varpro_noPunct ]] && echo "$varline" || echo done exec 3>&- # Close fd 3. exec 4>&- 

Vérifiez si cette solution vous aide à:

 use ssortingct; use warnings; my $f1 = $ARGV[0]; open FILE1, "<", $f1 or die $!; my $f2 = $ARGV[1]; open FILE2, "<", $f2 or die $!; open OUTFILE, ">", "cmp.txt" or die $!; my %seen; while () { $_ =~ s/[[:punct:]]//isg; $seen{lc($_)} = 1; } while () { my $next_line = ; $_ =~ s/[[:punct:]]//isg; if ($seen{lc($_)}) { print OUTFILE $_; } } close OUTFILE;