J'ai un tas de fichiers txt, je voudrais les sortir en minuscules, seulement alphabétique et un mot par ligne, je peux le faire avec plusieurs tr
commandes dans un pipeline comme ceci:
tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'
Est-il possible de le faire en une seule numérisation? Je pourrais écrire un programme C pour le faire, mais je me sens comme il y a une façon de le faire en utilisant tr
, sed
, awk
ou perl
.
Réponses:
Vous pouvez combiner plusieurs traductions (à l'exception des cas complexes impliquant des ensembles qui dépendent des paramètres régionaux qui se chevauchent), mais vous ne pouvez pas combiner la suppression avec la traduction.
Deux appels à
tr
sont susceptibles d'être plus rapides qu'un seul appel à des outils plus complexes, mais cela dépend beaucoup de la taille d'entrée, des proportions de différents caractères, de la mise en œuvretr
et des outils concurrents, du système d'exploitation, du nombre de noyaux, etc.la source
tr -s '[:upper:] [:punct:]' '[:lower:]\n' <doyle_sherlock_holmes.txt
printf 'A.AAAA,A' | tr -s '[:upper:] [:punct:]' '[:lower:][\n*]'
getsa\na\na'
, et la transformation pour... '[:lower:]\n'
pourrait ne pas nécessairement faire quoi que ce soit de toute'[:punct:]'
façon - certainstr
s tronqueront set1 pour correspondre à 2 et d'autres feront implicitement[\n*]
. Il vaut mieux simplement utiliser la gamme là-bas.Voici quelques approches:
GNU
grep
ettr
: trouver tous les mots et les mettre en minusculesGNU grep et perl: comme ci-dessus mais perl gère la conversion en minuscules
perl: recherchez tous les caractères alphabétiques et imprimez-les en minuscules (merci @steeldriver):
sed: supprimez tous les caractères non alphabétiques ou espaces, remplacez tous les caractères alphabétiques par leurs versions minuscules et remplacez tous les espaces par des retours à la ligne. Notez que cela suppose que tous les espaces blancs sont des espaces, pas d'onglets.
la source
perl -lne 'print lc for /[[:alpha:]]+/g'
aussi fonctionner? ou est-ce un mauvais style? (Je suis nouveau sur Perl et j'essaie d'apprendre!)sed -z 's/\W*\(\w\+\)\W*/\L\1\n/g'
sed
peut faire\w
maintenant? Cool!sed
le-z
commutateur ero delimit de GNU - il passe sur\0NUL
s plutôt que sur les nouvelles lignes. Assez cool quand vous faites quelque chose commetar -c . | tr -s \\0 | sed -z ...
- mais un peu lent.Oui. Vous pouvez le faire avec
tr
une locale ASCII (qui est, pour un GNU detr
toute façon, une sorte de sa seule compétence) . Vous pouvez utiliser les classes POSIX ou référencer les valeurs d'octets de chaque caractère par nombre octal. Vous pouvez également répartir leurs transformations sur plusieurs plages.La commande ci-dessus transformerait tous les caractères majuscules en minuscules, ignorerait complètement les caractères minuscules et transformerait tous les autres caractères en nouvelles lignes. Bien sûr, vous vous retrouvez avec une tonne de lignes blanches. Le
tr
-s
commutateur de répétitions queeze pourrait être utile dans ce cas, mais si vous l'utilisez à côté de la transformation[:upper:]
to,[:lower:]
vous finissez également par presser les caractères majuscules. De cette façon, il nécessite toujours un deuxième filtre comme ......ou...
... et donc ça devient beaucoup moins pratique que de le faire ...
... qui comprime le
-c
complément de caractères alphabétiques par séquence en une seule nouvelle ligne d'un morceau, puis transforme le haut en bas de l'autre côté du tuyau.Cela ne veut pas dire que des plages de cette nature ne sont pas utiles. Choses comme:
... peut être assez pratique car il convertit les octets d'entrée en tous les chiffres sur un spectre étalé de leurs valeurs. Ne gaspillez pas, ne voulez pas, vous savez.
Une autre façon de faire la transformation pourrait impliquer
dd
.Parce qu'il
dd
peut faire les deuxunblock
et leslcase
conversions en même temps, il pourrait même être possible de lui passer une grande partie du travail. Mais cela ne peut être vraiment utile que si vous pouvez prédire avec précision le nombre d'octets par mot - ou au moins vous pouvez remplir chaque mot avec des espaces à l'avance pour un nombre d'octets prévisible, carunblock
mange des espaces de fin à la fin de chaque bloc.la source
dd
s'impliquer :)