Pergunta:
Como posso encontrar correspondências de uma expressão regular de várias linhas em arquivos, sem pcregrep?
Preciso encontrar/imprimir a posição de cada ocorrência.
Infelizmente, o pcregrep não está presente e não tenho direitos para instalá-lo. Outras alternativas são grep
perl
sed
python
etc.
Um exemplo de expressão regular para pesquisar é:
Text\nLine
Contexto:
Um script fornece centenas de MB de texto estruturado em algumas dezenas de arquivos, mas infelizmente algumas linhas estão faltando (por vários motivos). Eu preciso verificar onde essas linhas estão faltando, procurando assim a sequência das linhas anteriores e seguintes.
Text
Missing //this line is sometimes missing.
Line
EDITADO:
Possível entrada
exemplo.txt
Text
Missing
Line
Text
Missing
Line
Text
Line
Text
Missing
Line
Saída possível:
exemplo.txt, linha 10
Algumas das tentativas sem sucesso:
pcregrep
# command not found
apt-get install pcregrep
# no permission, no su credentials, distro don't provide pcregrep, outdated sources, customer does not want changes on the serve, etc.
sed -r 's#(Text\nLine)#\1#' ./*
# print all lines, not only matches, no indication of file or line, etc.
grep 'Text\nLine' ./*
# Does not works on multi-lines
sed -n '/Text/,/Line/{p}' ./*
# Not the same regex, does not indicate result lines, etc.
As ferramentas Unix geralmente são orientadas a linhas e, portanto, não há como aplicar uma expressão regular em várias linhas de entrada usando a caixa de ferramentas padrão.
sed
pode ser feito para processar o arquivo de forma que seja capaz de detectar as linhas que você está procurando, mas fazemos isso estritamente usando operações em linhas individuais:Este
sed
script procura a stringText
no início de uma linha. Quando encontrado, ele anexa a próxima linha ao seu buffer com um\n
intermediário.Se o buffer agora corresponder
^Text\nLine
, o número da linha atual será gerado usando o=
comando emsed
. O número da linha de saída é o daLine
linha no arquivo.Observe que, embora a segunda expressão regular pareça corresponder a uma nova linha no arquivo, ela não corresponde. Ele corresponde a uma nova linha em seu buffer interno, que colocamos lá usando o
N
comando quando lemos a próxima linha do arquivo.Você provavelmente usaria isso em um loop se desejasse aplicá-lo a vários arquivos:
onde
pattern
seria um padrão de globbing de nome de arquivo comum que corresponda aos arquivos em que você está interessado.Se
vim
estiver instalado, você pode usá-lo noex
modo como:Veja também o
z
comando para dar contexto.Isso não imprime os nomes dos arquivos. Uma abordagem não muito eficiente
perl
poderia ser:Isso imprimirá o nome do arquivo junto com o número da linha onde ocorreu a correspondência.
Além disso, o contador de linha ($.) é redefinido ao atingir o fim de cada arquivo.