Regex da substring para a primeira ocorrência de outra substring

0

Eu preciso eliminar os arquivos textClipping de uma lista. Infelizmente alguns arquivos foram terrivelmente nomeados e contêm um retorno de carro. Eu preciso do regex perl para que corresponderia a cada caminho de /Volumes/ para .textClipping incluindo nova linha.

/Volumes/.*\.textClipping captura os dois primeiros arquivos .textClipping , mas não o terceiro, com a nova linha. Como alternativa, consegui capturar tudo, desde o primeiro /Volumes/ até o último .textClipping , mas isso também não é útil.

Alguma ideia? Muito obrigado.

/Volumes/folder/folder/file.doc
/Volumes/folder/folder/file.textClipping
/Volumes/folder/folder/file.doc
/Volumes/folder/folder/file.textClipping
/Volumes/folder/folder/fi  

le.textClipping
/Volumes/folder/folder/file.doc
    
por Robert Koszegi 24.08.2017 / 15:26

3 respostas

0

Você poderia fazer:

perl  -0777 -ae '@files = m~(/Volumes/(?:[^/\r\n]+/)+?[^/]+?\.textClipping\R)~g;print scalar(@files)," files found:\n",@files' file.txt

Onde:

  • -0777 leu o arquivo no modo "slurp"
  • -a modo autosplit

Regex:

 ~                      : regex delimiter
(                       : start group 1
    /Volumes/           : literally 
    (?:                 : start non capture group
        [^/\r\n]+       : 1 or more any character that is not a slash or line break
        /               : slash
    )+?                 : group repeated 1 or more times, not greedy (ie. the path)
    [^/]+?              : not a slash, 1 or more times, not greedy (ie. the filename)
    \.textClipping      : a dot with the extension
    \R                  : any kind of linebreak
)                       : end group 1
~g                      : regex delimiter, global flag

Saída:

3 files found:
/Volumes/folder/folder/file.textClipping
/Volumes/folder/folder/file.textClipping
/Volumes/folder/folder/fi

le.textClipping

Se você quiser manter todos os arquivos que não terminam com .textClipping

perl  -0777 -i.orig -ape 's~(/Volumes/(?:[^/\r\n]+/)+?[^/]+?\.textClipping\R)~~g' file.txt

O arquivo de entrada é modificado no local (opção -i ), o arquivo original é copiado com a extensão .orig

cat file.txt
/Volumes/folder/folder/file.doc
/Volumes/folder/folder/file.doc
/Volumes/folder/folder/file.doc
    
por 24.08.2017 / 17:06
0

Eu realmente aprecio as respostas. Obrigado pelo seu tempo. Peço desculpas se as coisas não estavam claras na minha pergunta. A resposta acabou por ser mais simples do que eu pensava inicialmente.

Para observar, o retorno de carro ou a nova linha no nome do arquivo é a seguinte: "file (CR) name.textClipping". Os arquivos de textclipping apenas fornecem o texto contido como o nome do próprio arquivo, que no meu caso é um pouco de retornos de carro. Dor no rabo!

Não obstante, isso funciona: / Volumes /.* \ n * .textClipping / g

Corresponde a cadeias de ocorrências que começam com "/ Volumes /", terminando com ".textClipping" com todo o resto.

Obrigado novamente por suas sugestões.

    
por 24.08.2017 / 17:55
0

Eu não poderia dizer pela sua pergunta onde, nos nomes dos arquivos, os caracteres da nova linha poderiam ser, então estou assumindo que eles poderiam estar em qualquer lugar. Isso torna a correspondência mais desafiadora.

A solução mais simples pode ser remover todas as novas linhas da entrada antes de remover os nomes de arquivos indesejados.

Eu fiz este script:

#!/usr/bin/perl                                                                                                                                            
$filename = "filelist.txt";                                                                                                                                
open(FILE, $filename) or die "Cant open $filename\n";                                                                                                      

# Undefine the record separator, so that the entire file will be read into a single string
# instead of an array with records separated by newlines
local $/ = undef;                                                                                                                                          
$lines = <FILE>;                                                                                                                                           
close(FILE);                                                                                                                                               
print "Before\n------\n";                                                                                                                                  
print $lines;                                                                                                                                              

# Remove all newlines                                                       
$lines =~ s/\n+//g;                                                                                                                                        
# Remove all "textClipping" files
$lines =~ s/\/Volumes\/[^ ]*.textClipping//g;                                                                                                              
# Turn multiple consecutive spaces into single spaces
$lines =~ s/ +/ /g;                                                                                                                                        

print "After\n-----\n";                                                                                                                                    
print "$lines\n";     

e alimentou o seu exemplo como filelist.txt:

/Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/fi
le.textClipping /Volumes/folder/folder/file.doc

que deu esta saída:

Before
------
/Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/fi
le.textClipping /Volumes/folder/folder/file.doc
After
-----
/Volumes/folder/folder/file.doc /Volumes/folder/folder/file.doc /Volumes/folder/folder/file.doc

Por fim, acho que você deve ser muito cauteloso ao usar o padrão sugerido em sua pergunta:

/Volumes/.*.textClipping

desde. irá capturar qualquer caractere, exceto uma nova linha, mas incluindo um espaço. Eu corri esse padrão nesta entrada, como sugerido pela sua pergunta:

/Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/file.doc /Volumes/folder/folder/file.textClipping /Volumes/folder/folder/fi
le.textClipping /Volumes/folder/folder/file.doc

e recebi essa saída, o que você não acha que é o que você quer:

/Volumes/folder/folder/fi
le.textClipping /Volumes/folder/folder/file.doc

Editar : você postou recentemente uma Resposta à sua própria pergunta, onde você cai nessa armadilha novamente, mas eu não tenho Reputação suficiente para postar um comentário sobre ela. Em vez de /Volumes/.*\n*.textClipping/g (que irá corresponder a espaços e, assim, possivelmente livrar-se de mais de um nome de cada vez), recomendo vivamente que considere /Volumes/[^ ]*\n*.textClipping/g ; o [^ ]* corresponderá a todos os espaços exceto .

    
por 24.08.2017 / 15:54

Tags