Eu tenho um arquivo de texto com linhas vazias separando blocos de texto. Eu gostaria de usar as ferramentas de linha de comando *NIX para embaralhar este arquivo, respeitando a estrutura do bloco. Em outras palavras, na saída, gostaria de ver a alteração da ordem dos blocos; as linhas e sua ordem dentro do bloco permanecem as mesmas.
Exemplo de arquivo de entrada:
line 1
line 2
line 10
line 20
line 30
line 100
line 200
O arquivo de saída (após o shuffle):
line 10
line 20
line 30
line 1
line 2
line 100
line 200
Obviamente, executar repetidamente deve fornecer uma ordem diferente de blocos.
A primeira linha do arquivo é sempre não vazia. Não há linhas duplas em branco. A última linha do arquivo está sempre vazia.
Escrevi um script Python muito simples que lê todas as linhas em uma lista de listas, embaralha e dá saída. Estou curioso para saber se poderia fazer isso com as ferramentas padrão do *NIX.
POSIXLY, você poderia fazer algo como:
Ou seja, prefixe cada linha com
<a-random-number-that-changes-with-each-paragraph>
o número da linha e, em seguida, classifique numericamente no primeiro número e depois no segundo para manter a ordem das linhas nos parágrafos e remova os números extras.Pode-se querer canalizar para
sed '$d'
remover a linha em branco à direita.Esteja ciente de que, com a maioria das
awk
implementaçõessrand()
, usa o tempo de época unix para semear o gerador de números pseudo-aleatórios, portanto, você pode obter o mesmo resultado se executar duas vezes no mesmo segundo (um bug histórico agora gravado na especificação POSIX, apesar de meus esforços, infelizmente ).Usando as ferramentas GNU, isso divide os parágrafos em grupos separados por NUL, embaralha-os e remove os NULs:
Abordagem alternativa sem usar NUL
Como nem todas as ferramentas suportam caracteres NUL, aqui está uma alternativa. Isso lê em parágrafos, substitui
~
por novas linhas, embaralha e depois converte o~
verso em novas linhas antes de exibir os resultados:Se o seu texto puder conter
~
, use outro caractere que o texto não contenha como separador de linha temporário.Usando perl:
Ou espalhe como um arquivo de script: