Classifique um arquivo de acordo com um campo começando com string

Classifique um arquivo de acordo com um campo começando com string

Suponha que eu tenha um arquivo tão estruturado

/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/zz/Books/Author-Zigniwe-Hisory-Medicine.pdf
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf

Eu gostaria de um arquivo classificado desta forma:

/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/zz/Books/Author-Zigniwe-History-Medicine.pdf

Ou seja, em ordem alfabética, de acordo com a stringAuthor-...

Como você pode ver, a posição de Author-...não é constante.

Como posso fazer isso?

Responder1

Experimente o seguinte bashcomando:

sort -t- -d -k2 -o output.txt input.txt

Possui quatro opções mais o nome do arquivo de entrada input.txt. Se este arquivo não estiver no diretório atual, você terá que fornecer o arquivo path/to/the/folder/input.txt. As opções e seus argumentos são os seguintes:

  • -t marca o separador de campos. Usamos -como separador, para que tudo antes e depois de -sejam considerados colunas separadas.
  • -d indica classificação de dicionário. Por exemplo, a Apple está antes de Berry.
  • -k2 indica a coluna pela qual classificar, neste caso a segunda coluna. Observe que a primeira coluna é tudo antes da primeira -. Por exemplo, /home/zz/BOOKS/Author. A segunda coluna está entre a primeira e a segunda -, ou seja Artemis,.
  • -o output.txtredireciona a saída classificada para um arquivo em vez de para o terminal.

Espero que isto ajude

Responder2

Embora seja um exagero para o presente exemplo por causa dosolução proposta na resposta do usuário68186, você poderia fazer algo mais geralmente assim no GNU awk:

gawk -F/ '
  function mycmp(i1,v1,i2,v2) {
    m = split(v1,a);
    n = split(v2,b);
    return a[m]"" > b[n]"" ? 1 : a[m]"" < b[n]"" ? -1 : 0
  }
  {
    lines[NR] = $0
  }
  END {
    PROCINFO["sorted_in"] = "mycmp";
    for(i in lines) print lines[i]
  }
' file

Observe que ele classifica de acordo com o valor lexical de tudo depois do último /- então se o formato for Author-<author name>-<title>.<extension>esse será

  • a string fixa Author-(que não tem efeito, pois tem o mesmo peso para todas as linhas); então
  • <author name>-; então
  • <title>.; então
  • <extension>

Isto é semelhante ao modo como o sortKEYDEF simples do GNU -t- -k2funciona, ou seja, a chave de classificação efetiva começa no final da <author name>linha e continua até o final da linha.

Um delimitador explícito é omitido das splitchamadas para que elas herdem o valor de FS, facilitando a alteração para sistemas que usam um separador de caminho diferente. As strings vazias anexadas ""na mycmpfunção forçam a comparação lexical mesmo se os nomes dos arquivos forem numéricos - veja por exemploComo o awk converte entre strings e números


Se preferir seguir o sortcomando, você pode aproveitar o GNU awkComunicações bidirecionais com outro processopara:

  • duplique o último /campo separado no início da string
  • passe o resultado para um sortcomando
  • leia novamente o resultado classificado, remova o prefixo duplicado e imprima

ou seja

gawk -F/ '
  BEGIN {OFS=FS; cmd = "sort -d"} 
  {print $NF $0 |& cmd} 
  END {
    close(cmd,"to"); 
    while(cmd |& getline){$1 = ""; print};
    close(cmd,"from")
  }
' file

Há um truque aqui, pois os caminhos absolutos (as linhas começam com /) implicam um campo inicial vazio; para lidar com caminhos relativos que você precisa alterar print $NF $0para print $NF,$0inserir o separador "ausente" e, talvez, usar um regex sub()em vez do mais simples $1 = ""para remover o elemento inicial.

Além de ser potencialmente mais rápido/mais eficiente em termos de memória do que a gawksolução pura, isso permite que outras sortopções sejam adicionadas diretamente, por exemplo. cmd = "sort -d -t " FS " -k1,1r".

informação relacionada