J'ai un fichier texte appelé entry.txt
qui contient les éléments suivants:
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
Je voudrais le diviser en trois fichiers texte: entry1.txt
, entry2.txt
, entry3.txt
. Leur contenu est le suivant.
entry1.txt :
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
entry2.txt :
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
entry3.txt :
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
En d'autres termes, le [
caractère indique qu'un nouveau fichier doit commencer. Les entrées ( [ entry*]
, où *
est un entier) sont toujours dans l'ordre numérique et sont des entiers consécutifs commençant de 1 à N (dans mon fichier d'entrée réel, N = 200001).
Existe-t-il un moyen de fractionner automatiquement un fichier texte en bash? Mon entrée entry.txt
réelle contient en fait 200 001 entrées.
la source
match
l'entrée:/^\[/ { name=$2 }
devrait suffire.[ blahblah blah blah ]
dans ma réponse.FS
, par exemple-F '\\[ | \\]'
.#S x
, où x est un nombre à 1, 2 ou 3 chiffres. Il suffit de les enregistrer dans x.dat. J'ai essayé:gawk '/^#S/{match($0, / [0-9]* /, k)} {print >k[1]".dat" }' myFile.txt
et quelques variantes de cela.gawk '/^#S/{match($0, /^#S (\s+?)([0-9]+)(\s+?)/, k)} {print >k[2]".txt" }' test.txt
fait l'affaire.2
Cependant, je ne comprends pas très bien le numéro du tableau .Avec csplit de GNU coreutils (Linux non embarqué, Cygwin):
Vous vous retrouverez avec un fichier vide supplémentaire
entry0.txt
(contenant la partie avant le premier en-tête).Le csplit standard n'a pas le
{*}
répéteur indéfini et la-b
possibilité de spécifier le format du suffixe, donc sur d'autres systèmes, vous devrez d'abord compter le nombre de sections et renommer les fichiers de sortie par la suite.la source
En perl, cela peut être fait beaucoup plus simplement:
la source
Voici un court one-liner awk:
Comment cela marche-t-il?
/^\[/
correspond aux lignes commençant par un crochet carré gauche, et{ofn=$2 ".txt"}
définit une variable sur le deuxième mot délimité par des espaces blancs comme nom de fichier de sortie. Alors,ofn
est une condition qui a la valeur true si la variable est définie (ce qui entraîne l'ignorance des lignes avant votre premier en-tête){print > ofn}
redirige la ligne actuelle vers le fichier spécifié.Notez que tous les espaces de ce script awk peuvent être supprimés, si la compacité vous rend heureux.
Notez également que le script ci-dessus a vraiment besoin que les en-têtes de section aient des espaces autour et non à l'intérieur. Si vous vouliez pouvoir gérer les en-têtes de section comme
[foo]
et[ this that ]
, vous auriez besoin d'un peu plus de code:Cela utilise la
sub()
fonction de awk pour supprimer les crochets de début et de fin plus les espaces. Notez que par comportement awk standard, cela réduira les espaces blancs (le séparateur de champ) en un seul espace (c'est[ this that ]
-à- dire est enregistré dans"this that.txt"
). Si la conservation de l'espace d'origine dans vos noms de fichiers de sortie est importante, vous pouvez expérimenter en définissant FS.la source
Cela peut être fait depuis la ligne de commande en python comme:
la source
C'est une façon un peu grossière, mais facile à comprendre: utilisez
grep -l '[ entry ]' FILENAME
pour obtenir les numéros de ligne à diviser à [entrée]. Utilisez une combinaison tête et queue pour obtenir les bons morceaux.Comme je l'ai dit; ce n'est pas joli, mais c'est facile à comprendre.
la source
Qu'en est-il de l'utilisation de awk avec
[
comme séparateur d'enregistrement et de l' espace comme séparateur de champ. Cela nous donne facilement les données à mettre dans le fichier comme$0
où il doit remettre le début supprimé[
et le nom de fichier comme$1
. Il ne nous reste alors plus qu'à gérer le cas particulier du 1er enregistrement qui est vide. Cela nous donne:la source
La réponse de terdon fonctionne pour moi mais j'avais besoin d'utiliser gawk, pas awk. Le manuel de gawk (recherchez 'match (') explique que l'argument tableau dans match () est une extension gawk. Cela dépend peut-être de votre installation Linux et de vos versions awk / nawk / gawk mais sur ma machine Ubuntu seul gawk a exécuté l'excellent de terdon répondre:
la source
Voici une solution Perl. Ce script détecte les
[ entryN ]
lignes et modifie le fichier de sortie en conséquence, mais ne valide pas, n'analyse pas ou ne traite pas les données de chaque section, il imprime simplement la ligne d'entrée dans le fichier de sortie.la source
Salut, j'ai écrit ce script simple en utilisant ruby pour résoudre votre problème
vous pouvez l'utiliser de cette façon:
je l'ai testé, et cela fonctionne très bien ..
la source
Je préfère l'
csplit
option, mais comme alternative, voici une solution GNU awk:parse.awk
Exécutez-le comme ceci:
la source
RT
variable semble être spécifique à gawk. Cette solution ne fonctionne pas pour moi en utilisant awk de FreeBSD.