AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 406382
Accepted
Vladislavs Dovgalecs
Vladislavs Dovgalecs
Asked: 2017-11-23 11:33:59 +0800 CST2017-11-23 11:33:59 +0800 CST 2017-11-23 11:33:59 +0800 CST

Embaralhamento de arquivo de várias linhas

  • 772

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.

awk text-processing
  • 3 3 respostas
  • 1304 Views

3 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2017-11-23T14:11:06+08:002017-11-23T14:11:06+08:00

    POSIXLY, você poderia fazer algo como:

    <file awk '
      BEGIN{srand(); n=rand()}
      {print n, NR, $0}
      !NF {n=rand()}
      END {if (NF) print n, NR+1, ""}' |
      sort -nk1 -k2 |
      cut -d' ' -f3-
    

    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 awkimplementações srand(), 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 ).

    • 8
  2. John1024
    2017-11-23T11:54:18+08:002017-11-23T11:54:18+08:00

    Usando as ferramentas GNU, isso divide os parágrafos em grupos separados por NUL, embaralha-os e remove os NULs:

    $ sed '1s/^/\n/; s/^$/\x00/' input | shuf -z | sed '1d; s/\x00//'
    line 100
    line 200
    
    line 10
    line 20
    line 30
    
    line 1
    line 2
    

    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:

    $ awk '{gsub(/\n/, "~")} 1' RS= input | shuf | awk '{gsub(/~/, "\n")} 1' ORS="\n\n"
    line 10
    line 20
    line 30
    
    line 100
    line 200
    
    line 1
    line 2
    

    Se o seu texto puder conter ~, use outro caractere que o texto não contenha como separador de linha temporário.

    • 5
  3. Jeff Schaller
    2017-11-23T12:02:40+08:002017-11-23T12:02:40+08:00

    Usando perl:

    perl -MList::Util -00 -e 'chomp(my @a=<>); print join("\n\n", List::Util::shuffle @a) . "\n";' < input
    

    Ou espalhe como um arquivo de script:

    #!/usr/bin/perl
    use List::Util 'shuffle';
    local $/ = "";  ## paragraph mode
    chomp(my @a = <>);
    print join("\n\n", shuffle @a) . "\n";
    
    • 5

relate perguntas

  • como posso alterar o caso do caractere (de baixo para cima e vice-versa)? ao mesmo tempo [duplicado]

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Matriz JSON para bash variáveis ​​usando jq

    • 4 respostas
  • Marko Smith

    A data pode formatar a hora atual para o fuso horário GMT? [duplicado]

    • 2 respostas
  • Marko Smith

    bash + lê variáveis ​​e valores do arquivo pelo script bash

    • 4 respostas
  • Marko Smith

    Como posso copiar um diretório e renomeá-lo no mesmo comando?

    • 4 respostas
  • Marko Smith

    conexão ssh. Conexão X11 rejeitada devido a autenticação incorreta

    • 3 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Marko Smith

    comando systemctl não funciona no RHEL 6

    • 3 respostas
  • Marko Smith

    rsync porta 22 e 873 uso

    • 2 respostas
  • Marko Smith

    snap /dev/loop em 100% de utilização -- sem espaço livre

    • 1 respostas
  • Marko Smith

    chave de impressão jq e valor para todos no subobjeto

    • 2 respostas
  • Martin Hope
    EHerman Matriz JSON para bash variáveis ​​usando jq 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux A data pode formatar a hora atual para o fuso horário GMT? [duplicado] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC Como posso copiar um diretório e renomeá-lo no mesmo comando? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve Como as permissões de arquivo funcionam para o usuário "root"? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe Altere o editor padrão para vim para _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey Como baixar o pacote não instalá-lo com o comando apt-get? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao Por que os diretórios /home, /usr, /var, etc. têm o mesmo número de inode (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg — o comando list-keys gera uid [ desconhecido ] depois de importar a chave privada para uma instalação limpa 2017-11-26 18:26:02 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve