J'ai souvent besoin de faire de nombreux remplaçants dans les fichiers. Pour résoudre ce problème, j'ai créé deux fichiers J'ai construit ce script, que j'espérais faire le remplacement. Tout d'abord, il lit Cependant, ma solution ne fonctionne pas bien. Lorsque j'exécute le script: p> Avez-vous des suggestions? p> Mise à jour: p> La réponse marquée fonctionne bien, cependant, j'utilise beaucoup ce script et il faut beaucoup d'heures pour terminer . Je propose donc une prime pour une solution pouvant compléter ces remplaçants beaucoup plus rapidement. Une solution à Bash, Perl ou Python 2 ira bien, à condition qu'il soit toujours compatible UTF-8. Si vous pensez qu'une autre solution utilisant d'autres logiciels couramment disponibles sur les systèmes Linux serait plus rapide, alors cela pourrait aller aussi bien, tant que d'énormes dépendances ne sont pas nécessaires. P> P> old.text code> et
nouveau.text code>. La première contient une liste de mots qui doivent être trouvés. La seconde contient la liste des mots qui devraient remplacer ceux-ci.
old.text code> une ligne à la fois, puis remplace les mots de cette ligne dans INPUT.TXT avec les mots correspondants à partir du fichier
nouveau.text code>. < / p>
SED code> ne sait pas où le numéro
$ code> se termine. li>
$ code> la variable est de changer sur "0 + 1", puis "0 + 1 + 1", quand il devrait passer à "1", puis "2". Li>
awk code> ne semble pas faire quelque chose de plus que la copie de l'entrée.txt exactement comme pour produire.txt. li>
ul>
12 Réponses :
Essayez de cibler la variable avec des guillemets doubles p>
LinefromNewwords = $ (sed -n "Numéro" $ "P NewWords.txt) P> blockQuote>
La variable $ NUMBER change sur "0 + 1", puis "0 + 1 + 1", quand il devrait passer à "1", puis "2". strong> li> li> ul> fais cela à la place: P>
Number = `EXPR $ Number + 1` P> blockQuote>
La ligne avec AWK n'apparaît pas faire quelque chose de plus que la copie de l'entrée.txt exactement comme pour produire.txt. strong> li> ul> awk ne prendra pas de variables en dehors de sa portée. Les variables définies par l'utilisateur dans AWK doivent être définies lorsqu'elles sont utilisées ou prédéfinies dans la déclaration de bourse de l'AWK. Vous pouvez inclure des variables shell en utilisant l'option
-v code>. p>
Voici une solution dans
bash code> qui ferait ce dont vous avez besoin. p>
Solution Bash: strong> P>
#!/bin/bash while read -r sub && read -r rep <&3; do sed -i "s/ "$sub" / "$rep" /g" main.file done <old.text 3<new.text
Pourquoi pas à
paste -d/ oldwords.txt newwords.txt |\ sed -e 's@/@ / @' -e 's@^@s/ @' -e 's@$@ /g@' >/tmp/$$.sed sed -f /tmp/$$.sed original >changed rm /tmp/$$.sed
à la ligne 6, la commande sed ne sait pas où se termine le numéro $. P>
XXX PRE> Je ne suis pas sûr de la citation, mais {Number} p fonctionnera - peut-être "$ {numéro} p" p>
La variable $ NUMBER change sur "0 + 1", puis "0 + 1 + 1", quand il devrait passer à "1", puis "2". P> blockQquote>
L'évaluation entière arithmétique dans Bash peut être effectuée avec $ (()) et est meilleure que
eval code> (eval = Evil). P>
s/\bni3\b/nÇ/g
Ce script Python 2 forme les anciens mots en une seule expression régulière, substitue ensuite le nouveau mot correspondant basé sur l'index de l'ancien mot qui correspondait. Les anciens mots ne sont assortis que s'ils sont distincts. Cette distinction est appliquée en entourant le mot dans R '\ B' qui est la limite de mot d'expression régulière.
Entrée provient de la commande Commandline (leur alternative a été commente que j'ai utilisée pour le développement au ralenti). La sortie est sur stdout p>
Le texte principal est numérisé une seule fois dans cette solution. Avec l'entrée de JayPals Réponse, la sortie est la même. P>
Total characters in text: 116413 Total words in text: 17114 Total distinct words in text: 209 Top 10 distinct word occurences in text: 2664 = 15.57%
Ceci devrait réduire strong> le temps par certains moyens que cela évite les em> inutiles em> boucles. suppose que vous avez Deux fichiers d'entrée, Nous allons créer un nouveau fichier texte qui agira en tant que script code> SED CODE> à votre fichier principal à l'aide des Fusionner deux fichiers d'entrée: h3>
AWK CODE> ONE-LINER: P>
sed -f merge.text input_file
[jaypal:~/Temp] cat input_file
12 adsflljl
12 hgfahld
12 ash;al
13 a;jfda
13 asldfj
15 ;aljdf
16 a;dlfj
19 adads
19 adfasf
20 aaaadsf
[jaypal:~/Temp] sed -f merge.text input_file
12 adsflljl
12 hgfahld
12 ash;al
13 a;jfda
13 asldfj
15 ;aljdf
16 a;dlfj
A adads
A adfasf
B aaaadsf
Cela pourrait fonctionner pour vous:
paste {old,new}words.txt | sed 's,\(\w*\)\s*\(\w*\),s!\\<\1\\>!\2!g,' | sed -i -f - text.txt
Voici un script Python 2 qui devrait être à la fois spatial et temps efficace: ici est en action: p> Modifier: Batte de chapeau à @ Paddy3118 pour la manipulation des espaces. P> p>
J'aime ce genre de questions, voici ma réponse:
Premier pour la Shake of Simplicity, pourquoi ne pas utiliser qu'un fichier avec source et traduction. Je veux dire: (nom de fichier chantethis) p> alors vous pouvez définir un séparateur approprié dans le script. (fichier remplacement de fichier.sh) p> prenez cet exemple (fichier changeme) p> appelez-le avec p> et vous obtiendrez p> prendre note de l'amusement "i" avec SED. "-J'ai" signifie remplacer dans le fichier source et "i" dans la commande S // signifie Ignorer CAS-CAS-EXTENDEMENT - Vérifiez votre implémentation SED - P> Notez bien que la boucle est horreur qu'un python ou un langage de script similaire. En fonction de vos besoins, vous pouvez faire une imbriquée pendant laquelle, un sur le fichier source et une intérieure en boucle les traductions (modifications). Écho à tous à STDOUT pour la flexibilité des tuyaux. P> #!/bin/bash
SEP=${1}
TRANSLATION=${2}
FILE=${3}
while read line
do
while read transline
do
origin=${transline%%${SEP}*}
dest=${transline##*${SEP}}
line=$(echo $line | sed "s/${origin}/${dest}/gI")
done < $TRANSLATION
echo $line
done < $FILE
Voici une solution à Perl. Il peut être simplifié si vous avez combiné vos listes de mots d'entrée dans une liste: chaque ligne contenant la carte des mots anciens et nouveaux. Fichier de mots ancien: P> $ perl replace.pl old.txt new.txt input.txt
12 adsflljl
12 hgfahld
12 ash;al
13 a;jfda
13 asldfj
15 ;aljdf
16 a;dlfj
A adads
A adfasf
B aaaadsf
Je ne sais pas pourquoi la plupart des affiches précédentes insistent sur l'utilisation d'expressions régulières pour résoudre cette tâche, je pense que cela sera plus rapide que la plupart (sinon la méthode la plus rapide).
use warnings; use strict; open (my $fh_o, '<', "old.txt"); open (my $fh_n, '<', "new.txt"); my @hay = <>; my @old = map {s/^\s*(.*?)\s*$/$1/; $_} <$fh_o>; my @new = map {s/^\s*(.*?)\s*$/$1/; $_} <$fh_n>; my %r; ; @r{@old} = @new; print defined $r{$_} ? $r{$_} : $_ for split ( /(\s+)/, "@hay" );
Edit - Je viens de remarquer que deux réponses comme les miennes sont déjà là ... Donc, vous pouvez simplement ignorer le mien :)
Je crois que ce script Perl, bien que ne pas utiliser Fancy SAD ou Awk Thkies, le travail équitablement ... P>
J'ai pris la liberté d'utiliser un autre format d'ancien_word à new_word: le format CSV. Si c'est trop compliqué pour le faire, faites-le-moi savoir et je vais ajouter un script qui prend votre vieille.txt, New.txt et construit le fichier CSV. P>
Prenez-le sur une course et faites-le-moi savoir ! P>
Au fait - si l'un de vous Perl Gurus ici peut suggérer une manière plus répandue de faire quelque chose que je fais ici, j'aimerai lire le commentaire: P>
#! /usr/bin/perl # getting the user's input if ($#ARGV == 1) { $LUT_file = shift; $file = shift; $outfile = $file . ".out.txt"; } elsif ($#ARGV == 2) { $LUT_file = shift; $file = shift; $outfile = shift; } else { &usage; } # opening the relevant files open LUT, "<",$LUT_file or die "can't open $signal_LUT_file for reading!\n : $!"; open FILE,"<",$file or die "can't open $file for reading!\n : $!"; open OUT,">",$outfile or die "can't open $outfile for writing\n :$!"; # getting the lines from the text to be changed and changing them %word_LUT = (); WORD_EXT:while (<LUT>) { $_ =~ m/(\w+),(\w+)/; $word_LUT{ $1 } = $2 ; } close LUT; OUTER:while ($line = <FILE>) { @words = split(/\s+/,$line); for( $i = 0; $i <= $#words; $i++) { if ( exists ($word_LUT { $words[$i] }) ) { $words[$i] = $word_LUT { $words[$i] }; } } $newline = join(' ',@words); print "old line - $line\nnewline - $newline\n\n"; print OUT $newline . "\n"; } # now we have all the signals needed in the swav array, build the file. close OUT;close FILE; # Sub Routines # # sub usage(){ print "\n\n\replacer.pl Usage:\n"; print "replacer.pl <LUT file> <Input file> [<out file>]\n\n"; print "<LUT file> - a LookUp Table of words, from the old word to the new one. \t\t\twith the following csv format: \t\t\told word,new word\n"; print "<Input file> - the input file\n"; print "<out file> - out file is optional. \nif not entered the default output file will be: <Input file>.out.txt\n\n"; exit; }
Une solution de Perl générale que j'ai constatée de bien fonctionner pour remplacer les clés sur une carte avec leurs valeurs associées est la suivante:
my %map = ( 19 => 'A', 20 => 'B', ); my $key_regex = '(' . join('|', keys %map) . ')'; while (<>) { s/$key_regex/$map{$1}/g; print $_; }
Avez-vous envisagé d'utiliser
sed code>?
J'ai mis à jour le script.
SED -I "S / $ $ I / $ J / G" ./MAIN.FILE CODE> - Ajout de l'espace dans cette action. Faites-moi savoir si cela ne fonctionne pas et nous pouvons regarder plus loin.
Avez-vous essayé de fusionner les deux fichiers et de le faire comme fichier de script SED?
J'ai ajouté une autre réponse à cela. Je ne sais pas si c'était une bonne idée d'ajouter un autre au lieu de l'édition de l'existence. Mais espérons que cela aide.
Je pense que la solution la plus rapide peut être facilement écrite dans C. Vous envisagez-vous que des langues de script?
Qu'est-il arrivé à la balise Python?