Correspondência de padrões e processamento de texto para listas de arquivos de música

3

Eu tenho dois arquivos e quero gerar um novo arquivo com as linhas encontradas em file2 , mas não em file1 . Os arquivos originais não são classificados.

Agora, aqui está a parte complicada. Algumas das linhas nos arquivos seguem os seguintes formatos:

./$ARTIST/$ALBUM/$N1 - $N2 - $TITLE.(flac|mp3)
./$ARTIST/$ALBUM/$N1 - $TITLE.(flac|mp3)
./$ARTIST/$ALBUM/$N1. $TITLE.(flac|mp3)

Em que $N1 e $N2 são números de um a três dígitos, por ex. 01 , 12 , 132

$ARTIST , $ALBUM e $TITLE podem ser compostos de qualquer sequência de caracteres alfanuméricos, incluindo. e - mas não /.

Eu quero que as linhas que terminem com flac ou mp3 sejam consideradas uma correspondência se $ARTIST , $ALBUM e $TITLE forem iguais e a linha correspondente a ser excluída.

Exemplo file1

./The BEATLES/white album/01. Revo-lution.flac
./123-123/234-234/01 - 02 - 3769.flac
./THE BEATLES/abbey road/cover.jpg

Exemplo file2

./The BEATLES/white album/01. Notinfile1.flac
./123-123/234-234/03. 3769.flac
./THE BEATLES/abbey road/cover.jpg

Arquivo de saída

./The BEATLES/white album/01. Notinfile1.flac

Editar :

Pensei no problema e encontrei uma solução, mas preciso de alguém para me ajudar a codificá-lo.

Para cada linha de ambos os arquivos, uma chave pode ser gerada usando o seguinte método. A comparação subseqüente das chaves entre os arquivos pode ser usada para gerar as linhas em file2 cujas chaves não correspondem àquelas em file1

Geração de chaves da seguinte forma:

Se a linha não terminar com flac ou mp3 , key é a própria linha.

Senão, verifique a primeira ocorrência de . ou - após o último / .

Se . for o caso, a chave será $ARTIST/$ALBUM/$TITLE , em que $TITLE é o que vier depois do ponto.

Se - for o caso, conte o número de traços na parte da linha após o último / .

Se um for encontrado, a chave será $ARTIST/$ALBUM/$TITLE , em que $TITLE é o que vier depois do traço.

Se forem encontrados mais de ou igual a dois traços, verifique se o que ocorre entre o primeiro e o segundo traço é puramente números e espaços. Se for, então $TITLE é após o segundo traço. Se não for, então $TITLE é após o primeiro traço.

Alguém por favor me ajudará a codificar isso?

    
por Ong Kuan Yang 14.04.2016 / 12:01

1 resposta

2

Geralmente é útil ter arquivos em ordem de classificação quando você deseja compará-los. O -u torna cada linha na saída única removendo quaisquer duplicatas.

sort -u file1 > file1.sorted
sort -u file2 > file2.sorted

comm pode comparar arquivos classificados, mas só pode comparar texto literal. Então, isso reduzirá o problema, mas só poderá filtrar as correspondências exatas. -1 remove linhas exclusivas do primeiro arquivo e -3 remove linhas comuns a ambos os argumentos do arquivo. Isso nos deixa com linhas que são exclusivas para o segundo arquivo.

comm -1 -3 file1.sorted file2.sorted > file2.reduced

Agora, precisamos fazer o trabalho complicado apenas para esse (espero) arquivo menor.

sed 's#^\./##' file2.reduced | while read line; do
  artist_album=${line%/*}
  filename=${line##*/}
  title=$(echo "$filename" | sed 's/^[0-9]\{1,3\}\. //;t;s/^[0-9]\{1,3\} - [0-9]\{1,3\} - //;t;s/^[0-9]\{1,3\} - //')
  extension=${title##*.}
  title=${title%.$extension}
  # We use fixed strings in case there are special chars in the file name
  # If the file names are "regex-save" we can use one grep instead:
  # ! grep -q -E "^\./$artist_album/.*$title\.(mp3|flac)\$" file1.sorted
  if ! grep -F "./$artist_album/" file1.sorted | grep -F -e "$title." | grep -q -E '(mp3|flac)$'; then
    echo "./$line"
  fi
done > results
    
por 14.04.2016 / 13:31