Imprimer des lignes randoms en respectant l'ordre du file source

J'ai un grand file text (~ 500K lignes) avec des phrases courtes (quelques mots longs). En outre, il y a un balisage XML dans la plupart des lignes. Finalement, le file text a été sortingé avant que le balisage ait été ajouté! L'ajout du balisage XML modifie le sorting alphabétique mais cela est souhaité.

Ma question est: Comment puis-je imprimer des lignes randoms en respectant l'ordre du file source?

Je sais que je pourrais utiliser la command shuf et sortinger le résultat. Le problème est que le balisage gâchera le genre.

Je pourrais aussi écrire un script python qui charge le file text dans une list, génère des nombres randoms, les sortinge et les utilise comme index pour extraire les lignes. Si possible, je préférerais les outils de command line standard * nix.

Données d'échantillon:

 <CITY>anaconda</CITY> city is in <STATE>montana</STATE> let's go to <CITY>rome</CITY> please find <CITY>berlin</CITY> where is <CITY>cairo</CITY> in <COUNTRY>egypt</COUNTRY> 

Par exemple, ce serait bien si je pouvais sortir les lignes 2 et 3. Les lignes 1, 3 et 4 sont également bonnes. Si je reçois les lignes 3, 1 et 4, ce n'est pas bon.

Utilisez ceci:

 nl file | shuf -n2 | sort -n | cut -f2- 
  • nl pour numéroter les lignes,
  • shuf pour mélanger et limiter la sortie à 2 lignes ( -n ),
  • sort pour rebuild l'ordre original,
  • et cut pour supprimer la numération de nl .

Il imprimera 2 lignes de votre file dans l'ordre d'origine du file. Utilisez shuf -n X , où X peut être n'importe quel nombre.

La sélection d'une ligne random à partir d'un file sans sorting (ou même savoir combien de lignes il y a!) Est couverte dans «L'art de la programmation informatique», Volume 2, Section 3.4.2 par Donald E. Knuth. C'est sortingvial à mettre en œuvre, par exemple:

 (echo foo; echo bar; echo zot) \ | perl -nle 'rand $. < 1 && ( $line = $_ ); END { print $line }' 

Ou essayez shuf , ce qui permet de sélectionner un certain nombre de lignes, bien que cela puisse nécessiter plus de memory que le select-one Knuth algo.

Vous pourriez le faire avec une boucle while et $ RANDOM comme:

 while read line; do if ((RANDOM%2)); then echo $line; fi; done < _path_ 

qui va imprimer environ la moitié des lignes, que vous pouvez contrôler avec la condition dans le if