Exclui as linhas que vêm depois de uma linha com um padrão específico no Shell

4

Estou tentando excluir todas as linhas após um padrão específico nos arquivos.

Eu tenho muitos arquivos, todos com a mesma estrutura:

Exemplo:

arquivo1

line 1
...
line x "here there is a specific pattern"
...
EOF

arquivo n

line 1
...
line x "here there is a specific pattern"
...
EOF

Eu tentei obter uma solução simples, mas como tenho muitos arquivos, continuo com um longo caminho: p

O padrão aparece uma vez em cada arquivo.

Então, eu tenho o número de todas as linhas que contém esse padrão e salve em um arquivo.

este é o meu código:

count=$(ls -f path_to_folder/*.txt | wc -l)
echo "Number of txt file : $count"
###


    for ((i=1;i < $count+1 ;i++))

    {

    vt=$(grep -n PATTERN $i.txt | cut -d : -f 1)
    echo $vt >> PATTERN_line.txt

    }

Cada linha em PATTERN_line.txt contém o número da linha, em cada arquivo, onde o padrão existe.

Agora, estou tentando usar esses números para excluir todas as linhas que vêm após o padrão até o final do arquivo.

Isso significa que preciso manter o arquivo da cabeça na linha patten que deve ser incluída.

Agradeço sua ajuda

    
por MGM 06.04.2018 / 12:16

4 respostas

10

Isso é muito trivial com os utilitários de processamento de texto. Por exemplo, usando sed :

sed '1,/pattern/!d' file

Ou seja, corresponde cada linha do primeiro ao com pattern e exclui todas as linhas não correspondentes. Então, substitua pattern pelo seu padrão. Se contiver / , você precisa escapar desses caracteres. Por exemplo, se o padrão for pattern-with/character :

sed '1,/pattern-with\/character/!d' file

Para realmente editar os arquivos (em vez de imprimir o fluxo editado para stdout), você pode usar o sinalizador -i :

sed -i '1,/pattern/!d' file

Você pode fazer um backup do arquivo original adicionando uma extensão para o arquivo antigo em -i . Tome cuidado aqui - você não deve incluir um espaço antes da extensão.

sed -i.backup '1,/pattern/!d' file

sed aceita vários argumentos de nome de arquivo. Por exemplo, para atuar em todos os arquivos não ocultos no diretório atual, você pode usar:

sed -i '1,/pattern/!d' *
    
por Zanna 06.04.2018 / 12:26
0

Obrigado @Zanna

Eu encontrei esta solução:

for ((i=1;i < $count+1 ;i++)) 

sed -n '/PATTERN/q;p' $i.txt > file_out$i.txt

Obrigado

    
por MGM 06.04.2018 / 12:45
0

Tente este script de shell. Leva 2 argumento como entrada. Primeiro argumento é o nome do arquivo de entrada. E o segundo argumento é o padrão requerido para pesquisar. Ele excluirá as linhas depois que o padrão for correspondido pela primeira vez.

#!/bin/bash

touch temp.txt

while read line
do
    echo "$line" | grep "$2" &> /dev/null
    if [ $? -eq 0 ]
    then
        echo "$line" >> temp.txt
        mv temp.txt $1
        echo "STATUS: Pattern matched. Successful operation..."
        exit 0
    fi
    echo "$line" >> temp.txt
done < $1

echo "STATUS: Pattern not found. No lines are deleted..."
rm -f temp.txt
    
por Ranajit Hore 06.04.2018 / 13:06
0

Outra solução, usando o awk:

awk '/specific-pattern/{stop=1} stop==0{print}' < input_file >> output_file

Enquanto a variável stop é 0 (que é, por padrão), awk imprimirá a linha atual. No entanto, se a linha atual corresponder à expressão regular / specific-pattern /, stop será definido como 1. Isso torna stop==0 falso, então o awk não executará mais a instrução print .

A entrada é lida de input_file e anexada ao output_file.

Se você quiser manter a linha com o padrão, inverta as duas partes do script awk.

    
por user234461 06.04.2018 / 17:43