Connexes, mais pas de réponses satisfaisantes: Comment puis-je diviser un gros fichier texte en morceaux de 500 mots environ?
J'essaie de prendre un fichier texte ( http://mattmahoney.net/dc/text8.zip ) avec> 10 ^ 7 mots tous sur une seule ligne, et de le diviser en lignes de N mots chacune. Mon approche actuelle fonctionne, mais est assez lente et laide (en utilisant un script shell):
i=0
for word in $(sed -e 's/\s\+/\n/g' input.txt)
do
echo -n "${word} " > output.txt
let "i=i+1"
if [ "$i" -eq "1000" ]
then
echo > output.txt
let "i=0"
fi
done
Des conseils sur la façon de rendre cela plus rapide ou plus compact?
text-processing
sed
awk
split
Cory Schillaci
la source
la source
Réponses:
En supposant que votre définition de mot est une séquence de caractères non vides séparés par des blancs, voici une
awk
solution pour votre fichier sur une seule lignela source
Utilisation
xargs
(17 secondes):Il utilise le
-n
drapeauxargs
dont définit le nombre maximum d'arguments. Il suffit de changer1000
de500
ou quoi que vous voulez limiter.J'ai fait un fichier de test avec 10 ^ 7 mots:
Voici les statistiques de temps:
la source
xargs
« de comportement de devis de décapagen
sera le plus lent, juste pour que vous le sachiez. Avec-n10
je l'ai annulé après environ 8 minutes d'attente ...Perl semble étonnamment bon dans ce domaine:
Créer un fichier avec 10 000 000 de mots séparés par des espaces
Maintenant, perl pour ajouter une nouvelle ligne après chaque 1000 mots
Horaire
vérifier les résultats
La solution awk acceptée a pris un peu plus de 5 secondes sur mon fichier d'entrée.
la source
Ne convient pas vraiment lorsque le nombre
N
de mots est un grand nombre, mais si c'est un petit nombre (et idéalement, aucun espace de début / de fin dans votre fichier d'une ligne), cela devrait être assez rapide (par exemple 5 mots par ligne):la source
paste
chaîne à la volée. Par exemple:tr -s '[[:blank:]]' '\n' < text8 | paste -d' ' $(perl -le 'print "- " x 1000')
set
etc ... et même dans ce cas, il y a un nombre maximum d'arguments spécifique au système (je ne connais pas toutes les saveurs depaste
mais Je pense qu'avec certaines implémentations, il y a des limites quant au nombre d'arguments / fichiers d'entrée et / ou la longueur de la ligne de sortie ...)La même commande sed peut être simplifiée en spécifiant le nombre de modèles d'espace de mots que vous souhaitez faire correspondre. Je n'avais pas de gros fichiers de chaîne pour le tester, mais sans les boucles de votre script d'origine, cela devrait fonctionner aussi vite que votre processeur peut diffuser les données. Avantage supplémentaire, cela fonctionnera aussi bien sur les fichiers multi-lignes.
la source
La vénérable
fmt(1)
commande, bien qu'elle ne fonctionne pas strictement sur "un nombre particulier de mots", peut assez rapidement enrouler de longues lignes à un objectif particulier (ou maximum) de largeur:Ou avec perl moderne, pour un nombre spécifique de mots, disons 10, et en supposant un seul espace comme limite de mot:
la source
La
pr
commande coreutils est un autre candidat: la seule ride semble être qu'il faut forcer la largeur de page pour qu'elle soit suffisamment grande pour accueillir la largeur de sortie.En utilisant un fichier créé à l'aide du générateur de 10 000 000 de mots de @ Glenn_Jackman,
où les dénombrements sont confirmés comme suit
[La solution Perl de Glenn est encore un peu plus rapide, ~ 1,8 s sur cette machine].
la source
dans Go je l'essayerais comme ça
la source